1

Today i came across a seemingly strange issue regarding resolving multiple implementations of a type in combination with property injection of a optional dependency, in my case a logger instance.

I am using Unity 2.1 and UnityConfiguration in order to realize convention-based configuration.

I am using the SetAllPropertiesConvention in order to inject an implementation of ILogger into many of my types.

If i'm resolving a single implementation using for example container.Resolve<IProcessor>() the instance of ILogger is properly injected.

However, if i'm resolving multiple instances of that type using container.ResolveAll<IProcessor>() the property remains null.

Here my registration code:

container.RegisterInstance(typeof (ILogger), LoggerService.GetLogger());
container.Configure(c => c.Scan(scan =>
                    {
                        scan.AssembliesInBaseDirectory(a => a.FullName.StartsWith("My.Company"));
                        scan.InternalTypes();
                        scan.With<AddAllConvention>().TypesImplementing<IFetchDataCommand>();
                        scan.With<AddAllConvention>().TypesImplementing<IPrintConverter>();
                        scan.With<SetAllPropertiesConvention>().OfType<ILogger>();
                    }));

SetAllPropertiesConvention itself uses the following code to register the logger es property injected:

IEnumerable<PropertyInfo> properties =
                type.GetProperties().Where(p => p.CanWrite && p.PropertyType == interfaceType);

foreach (PropertyInfo property in properties)
{
    registry.Register(null, type).WithInjectionMembers(new InjectionProperty(property.Name));
}

Is this a bug, or did i something wrong. Any ideas?

1
  • Can you provide your registration code? Commented Apr 24, 2013 at 19:41

1 Answer 1

1

If you are using RegisterType<T, U>() method to register your dependencies without any parameters you won't register different implementations. You need to provide named registrations, like this:

RegisterType<IProcessor, MyProcessor1>("MyProcessor1")
RegisterType<IProcessor, MyProcessor2>("MyProcessor2")

ResolveAll() does not include mapping without name.

EDIT:

Not sure why you cannot configure property injection using convention, but you can set it after type is building up. Something like this:

    var container = new UnityContainer();
    container.RegisterInstance(typeof (ILogger), new Logger());

    container.Configure(x => 
        {
            x.AfterBuildingUp<IFetchDataCommand>().Call((c,s) => s.Logger = c.Resolve<ILogger>());
            x.Scan(
                scan =>
                    {
                        scan.Assembly(Assembly.GetExecutingAssembly());
                        scan.InternalTypes();
                        scan.With<AddAllConvention>().TypesImplementing<IFetchDataCommand>();
                        scan.WithSetAllPropertiesConvention().OfType<ILogger>();
                    });
        });

    var dataCommand = container.ResolveAll<IFetchDataCommand>().ToArray();

    Assert.That(dataCommand[0].Logger, Is.Not.Null);
    Assert.That(dataCommand[1].Logger, Is.Not.Null);

This line is important :

x.AfterBuildingUp<IFetchDataCommand>().Call((c,s) => s.Logger = c.Resolve<ILogger>());

And my classes:

public interface IDataCommand
{
    ILogger Logger { get; set; }
}

public class Logger : ILogger
{
    public string Name { get; set; }
}

public class FetchDataCommand : IDataCommand
{
    public ILogger Logger { get; set; }
}

public class StoreDataCommand : IDataCommand
{
    public ILogger Logger { get; set; }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your answer, but that's not my problem. I do get multiple Instances of that type but if i resolving all implementations using ResolveAll() the property MyProcessor1.Logger isn't injected.
I extended my question, have a look. Thanks
see I updated my answer, you need to set property after building up the type : x.AfterBuildingUp<IFetchDataCommand>().Call((c,s) => s.Logger = c.Resolve<ILogger>());
Thank you very much for that solution. Although, that forces me to define the logger property on the interface of the types i want to "multi-resolve". In my opinion it is A solution but not The solution, so i will mark your answer as usefull. (Edit: Ups i have not enough reputation)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.