1

I have a problem with my spring.net configuration:

<object id="O1">
    <constructor-arg ref="Dep1"/>
    <constructor-arg ref="Dep2"/>
</object>

This is part of my generic configuration used by all applications. Some applications define Dep2 in their configuration and some don't. Can I make second constructor arg return null (instead of reporting error) when specific application doesn't define Dep2?
I would like to solve this without overriding O1 definition in app specific configuration.

Thanks.

Filip
  • 3,257
  • 2
  • 22
  • 38

1 Answers1

2

You can create an IFactoryObject that returns null and configure it in your "specific application" config file. See this related question: How do I configure a NULL object in Spring.Net.

Furthermore, if Dep2 is an optional dependency (e.g it can be null or it has a sensible default) than it is probably better to define it as a property and use property injection.

Edit

I expected this to work, but it actually doesn't, because an IFactoryObject that returns null is treated as an error by the spring container:

From the api docs on IFactoryObject.GetObject()

If this method is being called in the context of an enclosing IoC container and returns , the IoC container will consider this factory object as not being fully initialized and throw a corresponding (and most probably fatal) exception.

Classes:

public class MyClass
{
    public MyOtherClass Prop { get; set; }

    public MyClass(MyOtherClass ref1)
    {
    }
}

public class MyOtherClass
{
}

public class NullFactoryObject : IFactoryObject
{
    public object GetObject()
    {
        return null;
    }

    public Type ObjectType
    {
        get { return typeof(MyOtherClass); }
    }

    public bool IsSingleton
    {
        get { return true; }
    }
}

in configfile1.xml:

<object id="MyObject" type="q9292066_null_object_reference.MyClass, q9292066_null_object_reference">
  <constructor-arg name="ref1" ref="ref1" />
</object>

in configfile2.xml:

<object id="ref1" 
        type="q9292066_null_object_reference.NullFactoryObject, q9292066_null_object_reference" />
Community
  • 1
  • 1
Marijn
  • 10,367
  • 5
  • 59
  • 80
  • Marijn, can you clarify this a bit more. I implemented O1FactoryObject. What is recommended way of passing Dep1/Dep2 to O1FactoryObject? If I pass it as property/constrcutor ref, I will face the same problem as in my question. If I pass Dep1/Dep2 as simple strings I will need to fetch them in O1FactoryObject code. Is that correct solution? Together with depends-on for handling initialization order? Thanks. – Filip Feb 17 '12 at 13:48
  • hmmm, this actually doesn't work - it appears that factory objects are not allowed to return null. I'll look a bit further. – Marijn Feb 17 '12 at 15:29
  • Yes, I've got error also. Even if you find a way for this to work, I still need to declare ref1. That isn't big problem since I can declare ref1 with NullFactoryObject in generic configuration and override it in app specific conf. Still, can it be done without declaring ref1 or there is no way to intercept loading process before Spring.NET checks references? – Filip Feb 17 '12 at 16:10
  • 1
    No, not really. IMO there are two smells: (1) O1's type has a constructor argument that can be null (2) You define a `Ref2` dependency that does not necessarily have to be fulfilled. Alarm bells! Why don't you want to override the O1 configuration? IMO this needs a structural improvement instead of the hacks we're trying to come up with now. – Marijn Feb 22 '12 at 07:57
  • Marijn, I don't see why should first problem raise alarm. Optional constructor argument isn't anything unusual. Also, I can define that argument as property, but I will still have the same problem. I don't want to override O1 configuration because I want to reduce amount of configuration in specific configuration. Those specific configurations are written by other department and I want to reduce possible changes in their configuration as much as possible. Anyway, thank you for your help and I will report my solution here (if I find one). – Filip Feb 22 '12 at 09:16
  • I'm very interested to see what you come up with. I agree that an optional constructor argument is not unusual (same as an overloaded constructor basically), but from the configuration in your question it looks as if it's required. But that at the same time it's "sort of" optional because you can supply a `null` dependency. – Marijn Feb 22 '12 at 10:00
  • 1
    Marijn, it seems that your solution work ... in [Java version](http://stackoverflow.com/questions/2163182/intentionally-setting-a-spring-bean-to-null). Maybe Spring.NET should behave same way? – Filip Feb 22 '12 at 13:53