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?

NooBody
  • 21
  • 4

1 Answers1

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; }
}
Jevgenij Nekrasov
  • 2,690
  • 3
  • 30
  • 51
  • 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. – NooBody Apr 25 '13 at 06:22
  • I extended my question, have a look. Thanks – NooBody Apr 25 '13 at 06:54
  • see I updated my answer, you need to set property after building up the type : x.AfterBuildingUp().Call((c,s) => s.Logger = c.Resolve()); – Jevgenij Nekrasov Apr 25 '13 at 09:05
  • 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) – NooBody Apr 25 '13 at 17:30