1

今天我遇到了一个看似奇怪的问题,即解决一个类型的多个实现以及可选依赖项的属性注入,在我的例子中是一个记录器实例。

我正在使用 Unity 2.1 和 UnityConfiguration 来实现基于约定的配置。

我正在使用SetAllPropertiesConvention将 ILogger 的实现注入到我的许多类型中。

如果我正在使用例如 ILogger 的实例来解决单个实现,container.Resolve<IProcessor>()则该实例已正确注入。

但是,如果我使用该属性解析该类型的多个实例,则container.ResolveAll<IProcessor>()该属性仍然为空。

这是我的注册码:

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本身使用以下代码来注册注入的 logger es 属性:

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));
}

这是一个错误,还是我做错了什么。有任何想法吗?

4

1 回答 1

1

如果您使用RegisterType<T, U>()方法来注册没有任何参数的依赖项,您将不会注册不同的实现。您需要提供命名注册,如下所示:

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

ResolveAll()不包括没有名称的映射。

编辑:

不知道为什么你不能使用约定配置属性注入,但你可以在类型建立后设置它。像这样的东西:

    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);

这条线很重要:

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

还有我的课:

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; }
}
于 2013-04-24T19:45:51.923 回答