首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于自定义条件解析依赖关系

基于自定义条件解析依赖关系
EN

Stack Overflow用户
提问于 2013-04-20 06:45:27
回答 1查看 1.1K关注 0票数 3

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

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

本质上,我希望将事件总线声明为单例,并根据某些条件注入它们。我想避免仅仅为了区分解决方案而对事件总线进行子类型化。

我在java中使用过Google Guice IoC,它允许参数的元数据解析。在java中,它允许我做一些与此类似的事情。

示例:

代码语言:javascript
复制
public A([SpecialUseAggregator]IEventAggregator something)
public B([SpecialUseAggregator]IEventAggregator something)

public E([AnotherUseAggregator]IEventAggregator something)
public F([AnotherUseAggregator]IEventAggregator something)

有什么建议吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-04-24 12:53:46

Autofac没有用于注册的/use属性。一种解决方案是使用Named/Keyed注册功能。

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

代码语言:javascript
复制
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();

如果你仍然想使用属性,那么你可以使用Autofac,因为它有所有需要的扩展点,它只需要更多的代码来教Autofac关于你的属性并正确使用它。

如果您正在使用扫描注册您的类型,则不能使用简单的WithParameter注册,但是您可以在Autofac中使用Metadata facility

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

代码语言:javascript
复制
public class EventAggrAttribute : Attribute
{
    public string Key { get; set; }

    public EventAggrAttribute(string key)
    {
        Key = key;
    }
}

并给你的类赋值:

代码语言:javascript
复制
[EventAggrAttribute("SpecialUseAggregator")]
public class AViewModel
{
    public AViewModel(IEventAggreator eventAggreator)
    {
    }
}

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

代码语言:javascript
复制
contianerBuilder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
            .Where(t => t.Name.EndsWith("ViewModel"))
            .OnPreparing(Method)
            .WithMetadataFrom<EventAggrAttribute>();

最后,您需要OnPreparing事件,您可以在其中执行基于元数据的解析:

代码语言:javascript
复制
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};
}

这是gist of a working unit test.

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16114554

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档