根据自定义条件解决依赖关系

And*_*hov 3 autofac

我的应用程序依赖于多个事件总线对象,这些对象是基本的发布/订阅通知模型(http://caliburn.codeplex.com/wikipage?title=The%20Event%20Aggregator).

我想要做的是与一组组件共享某些聚合器实例.假设组件我有一个在组件A,B和C之间共享的事件总线,然后是在D,E,F之间共享的另一个事件总线.

我基本上想要将事件总线声明为单例并根据某些条件注入它们.我有点想避免对事件总线进行分类,只是为了区分分辨率.

我在java中使用了Google Guice IoC,它允许参数的元数据解析.java中的Aka让我得到了与此相当的东西.

例:

public A([SpecialUseAggregator]IEventAggregator something)
public B([SpecialUseAggregator]IEventAggregator something)

public E([AnotherUseAggregator]IEventAggregator something)
public F([AnotherUseAggregator]IEventAggregator something)
Run Code Online (Sandbox Code Playgroud)

有什么建议?

nem*_*esv 5

Autofac没有/使用注册属性.一种解决方案是使用命名/键控注册功能.

因此,您需要EventAggreator使用不同的名称/密钥注册两个,并且在注册消费者类型A,B等时,您可以使用它WithParameter告诉Autofac IEventAggreator它应该用于给定的实例:

var contianerBuilder = new ContainerBuilder();
contianerBuilder.Register(c => CreateAndConfigureSpecialEventAggregator())
                        .Named<IEventAggreator>("SpecialUseAggregator");
contianerBuilder.Register(c => CreateAndConfigureAnotherUseAggregator())
                        .Named<IEventAggreator>("AnotherUseAggregator");

contianerBuilder.RegisterType<A>).AsSelf()
                 .WithParameter(ResolvedParameter
                 .ForNamed<IEventAggreator>("SpecialUseAggregator"));
contianerBuilder.RegisterType<B>().AsSelf()
                 .WithParameter(ResolvedParameter
                 .ForNamed<IEventAggreator>("SpecialUseAggregator"));
contianerBuilder.RegisterType<C>).AsSelf()
                 .WithParameter(ResolvedParameter
                 .ForNamed<IEventAggreator>("AnotherUseAggregator"));
contianerBuilder.RegisterType<D>().AsSelf()
                 .WithParameter(ResolvedParameter
                 .ForNamed<IEventAggreator>("AnotherUseAggregator"));
var container = contianerBuilder.Build();
Run Code Online (Sandbox Code Playgroud)

我仍然想使用属性,然后你可以用Autofac来做它,因为它有所有必需的扩展点,它只需要一些代码来教Autofac关于你的属性并正确使用它.

如果您使用扫描注册类型,则无法使用轻松使用WithParameter注册,但是您使用Autofac中的元数据工具:

只需创建一个保存EventAggreator键的属性:

public class EventAggrAttribute : Attribute
{
    public string Key { get; set; }

    public EventAggrAttribute(string key)
    {
        Key = key;
    }
}
Run Code Online (Sandbox Code Playgroud)

并归类你的类:

[EventAggrAttribute("SpecialUseAggregator")]
public class AViewModel
{
    public AViewModel(IEventAggreator eventAggreator)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,当您进行扫描时,您需要使用WithMetadataFrom注册元数据:

contianerBuilder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
            .Where(t => t.Name.EndsWith("ViewModel"))
            .OnPreparing(Method)
            .WithMetadataFrom<EventAggrAttribute>();
Run Code Online (Sandbox Code Playgroud)

最后,您需要OnPreparing执行基于元数据的解决方案的事件:

private void Method(PreparingEventArgs obj)
{
    // Metadata["Key"] is coming from the EventAggrAttribute.Key
    var key = obj.Component.Metadata["Key"].ToString();
    ResolvedParameter resolvedParameter = 
        ResolvedParameter.ForNamed<IEventAggreator>();
    obj.Parameters = new List<Parameter>() { resolvedParameter};
}
Run Code Online (Sandbox Code Playgroud)

这是工作单元测试的要点.