Search code examples
dependency-injectionservicestackinversion-of-control

ServiceStack IOC. AutoWire(this) tries to inject public properties that are not registered in the Container


When using ServiceStack and its IoC/DI framework, I have the following problem:

The DI framework injects null into a property, and that property type is not registered in the Container.

class DependencyInjectedA : IDependencyInjectedA
{
    public DependencyInjectedB { get; set; }
}

class DependencyInjectedB 
{
    public Dictionary<DateTime, SomeClass> MyProperty { get; set; }
}

And in my Configure method:

public override void Configure(Container container)
{
    base.Configure(); // here we have code like 'Container.AutoWire(this);'
    container.AddSingleton<IDependencyInjectedA, DependencyInjectedA>();
    container.AddSingleton<DependencyInjectedB>();
}

So, in the parent class, I do

Container.AutoWire(this);

and the reason behind the AutoWire call is so that I can get the DI framework to inject the descendants of this. I was under the impression that only types that was registered in the Container would be dependency injected, and also that it would be descendants of this, but it seems that also the MyProperty in DependencyInjectedB gets injected, and then with a null value, since we have not added Dictionary<DateTime, SomeClass> to the Container.

Here is a (somewhat edited) picture of what happens: the DI injects NULL, when I think it shouldn't do it.

enter image description here

Mythz actually says it here:

Autowire Registration You can register dependencies so that all the dependencies are automatically auto-wired. Just like the hooks above, once resolved Funq will create a new instance resolving dependencies for the constructor that has the most arguments as well as all public properties.

Questions:

  • How can I then have public properties that I do not want to be injected?
  • Is there a way to inject only the types that is registered in the container (.AddXXX)?

Solution

  • This is the behavior of Funq's autowiring that does both public property and constructor injection.

    Specifically Funq's autowiring behavior will inject any properties which are:

    • public
    • writable (i.e. has a public setter)
    • Is not a ValueType or string
    • It's full type name is not registered in Container.IgnorePropertyTypeFullNames collection

    So if you don't want properties injected they cannot meet all the above criterias. If it's just one property Type that you want to prevent injecting, you can register the full type name in:

    Container.IgnorePropertyTypeFullNames.Add(typeof(DependencyInjectedB).FullName);
    

    Alternatively change it so it's not public, otherwise you shouldn't use Funq's AutoWiring APIs containing this behavior, you'd instead register the dependency using a custom factory function, e.g:

    container.AddSingleton<IDependencyInjectedA>(c => new DependencyInjectedA());