Reputation: 21
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?
Upvotes: 1
Views: 979
Reputation: 2760
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; }
}
Upvotes: 1