Question

I have a Service created with ServiceStack. I am using Funq for my Dependency Injection as it comes with ServiceStack by default, but this may be behaviour exhibited by other DI containers.

I register my types on startup:

this.AppContainer.RegisterAs<ConcreteDownloadServices, IDownloadServices>();`

I have this constructor in a class:

private readonly IDownloadServices downloadServices;

public ExampleService(IDownloadServices downloadServices)
{
    this.downloadServices = downloadServices;
}

And the constructor of my concrete implementation is:

public ConcreteDownloadServices()
{
    this.ArbitraryProperty = "ArbitraryString";
}

Everything resolves fine and I can step into the code and see things working as expected. However, AbritraryProperty does not get set properly. I can step through and see it set to the string value, but as soon as the code returns to the calling code (in this example, it would be the constructor of ExampleService) ArbitraryProperty is now null.

  1. Is this behaviour by design?
  2. If it is by design, does using DI mean that I shouldn't be doing anything in the constructors of my concrete implementations?
  3. If it is by design, what's the correct way to set default values for auto properties?
  4. If it is not by design, then what's going on?
Was it helpful?

Solution

Edit:

I've decided this is never desired behavior so I've just checked in a commit to enforce that Funq doesn't autowire string (and ValueType) properties. The new behavior will be available in the next version of ServiceStack (v3.9.34).

Existing behavior

RegisterAs is an Autowired API, i.e:

Container.RegisterAs<ConcreteDownloadServices, IDownloadServices>();

This tells ServiceStack's IOC to populate every public property with dependencies resolved by the IOC. Which because it is a string public property will try to resolve the registered string from the IOC. In code terms, this is happening under the hood:

new ConcreteDownloadServices { 
    ArbitraryProperty = Container.TryResolve<string>()
};

Which because you don't have any "string" registered will override the property with null. Only public properties are auto-wired so you can avoid this behavior by changing it to an protected, private or internal property.

Otherwise you can override the default IOC behavior by registering a custom delegate factory which gives you full control over the construction of your dependency, e.g:

container.Register<IDownloadServices>(c => new ConcreteDownloadServices());

OTHER TIPS

Some members of our devteam just spent some time debugging a similar issue.

A RegisterAs class used in one of our unittests has a public member: public List Mails { get; set; }

When this class is resolved through Funq, the member is set to null, even though it is was set in the constructor.

Our teammembers agree that it is wierd that this member is set to null by Funq, when the member isnt of a type that is registered as a Container.RegisterAs<>.

We are using ServiceStack version 4.0.33

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top