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

标签 autofac

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

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

我基本上想将事件总线声明为单例并根据某些标准注入(inject)它们。我有点想避免为了区分分辨率而对事件总线进行子类型化。

我在 Java 中使用了 Google Guice IoC,它允许对参数进行元数据解析。在 Java 中又名,它允许我得到与此等效的东西。

例子:

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

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

有什么建议吗?

最佳答案

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

因此您需要注册两个具有不同名称/键的 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();

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

如果您通过扫描注册您的类型,您将无法轻松使用 WithParameter 注册,但是您可以使用 Metadata facility在 Autofac 中:

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

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

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

并归类你的类:

[EventAggrAttribute("SpecialUseAggregator")]
public class AViewModel
{
    public AViewModel(IEventAggreator eventAggreator)
    {
    }
}

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

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

最后,您需要执行基于元数据的解析的 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};
}

这里是 gist of a working unit test.

关于autofac - 根据自定义条件解决依赖关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16114554/

相关文章:

asp.net-mvc - AOP vs MVC FilterAttributes vs Interceptors

asp.net-mvc-4 - MVC4 MEF 插件和 Controller 命名空间

c# - 使用 Autofac 在我的组件类 Azure Functions 中注入(inject) ILogger 实例

c# - 使用 Autofac 的 IIndex 解析多个 Keyed 实例

.net - 在Autofac中,如何更改在调用Build之后注册的实例?

wcf - 带 wcf 的 Autofac

inversion-of-control - Autofac - 如何从单例中解析 ISomething 的 Func,其中 ISomething 是 InstancePerHttpRequest

c# - 注入(inject)具有多个相同类型参数的构造函数

asp.net-web-api2 - Autofac 作业激活器与 Hangfire 抛出异常 DependencyResolutionException

prism - Autofac 中 Prism 集成的状态如何?