替换 Autofac 中的注册

问题描述 投票:0回答:3

我有一个进行数据处理的应用程序。有

class Pipeline {
  IEnumerable<IFilter> Filters {get; set;}

我将过滤器实现注册为

builder.RegisterType<DiversityFilter>().As<IFilter>();
builder.RegisterType<OverflowFilter>().As<IFilter>();
...

到目前为止一切顺利。现在,为了进行实验和微调,我希望能够使用程序(脚本)覆盖配置文件中的任何过滤器实现,该程序(脚本)将从标准输入读取数据,对其进行处理并将数据发送到标准输出。我已经实现了一个带有“fileName”、“args”和“insteadOf”自定义属性的模块,在 xml 中描述了模块并调用了它。

在模块中,我注册了“ExecutableFilter”,但是如何让它运行“而不是”所需的服务?如果我尝试这样做:

builder.RegisterType<ExecutableFilter>().As<DiversityFilter>()

然后我得到一个异常“类型‘ExecutableFilter’不能分配给服务‘DiversityFilter’。”。好吧,这是合乎逻辑的。但我的选择是什么?

autofac
3个回答
11
投票

一旦您通过窃听覆盖了 IFilter“After”的注册,您将无法从容器中解析它,因为新的注册将被激活,从而导致循环查找。

相反,创建并注册一个模块来挂钩过滤器的创建,并用“窃听”模块替换该实例:

class WiretapModule : Module
{
  override void AttachToComponentRegistration(
           IComponentRegistration registration,
           IComponentRegistry registry)
  {
    if (registration.Services.OfType<KeyedService>().Any(
          s => s.ServiceKey == After && s.ServiceType == typeof(IFilter))) 
    {
      registration.Activating += (s, e) => {
        e.Instance = new WireTap((IFilter)e.Instance, new ExecuteProvider(fileName, args))
      };
    }
  }
}

(交叉发布到 Autofac 小组:https://groups.google.com/forum/#!topic/autofac/yLbTeuCObrU


2
投票

您所描述的部分是容器工作,部分是业务逻辑。挑战在于保持关注点分离。 IMO,容器应该做它应该做的事情,即构建和提供实例或其集合。在这种情况下,它不应该执行“而不是”操作。我宁愿用足够的信息“丰富”服务,以便管道做出决定。

“丰富”可以通过使

ExecutableFilter
实现更独特的界面来实现。

interface IInsteadOfFilter : IFilter { }

...

builder.RegisterType<ExecutableFilter>().As<IFilter>();

...

class Pipeline
{
    IEnumerable<IFilter> Filters {get;set;}

    public void DoTheFiltering()
    {
        var filters = Filters.OfType<IInsteadOfFilter>();
        if (!insteadof.Any())
            filters = Filters;

        foreach(var filter in filters)
        {
            ...
        }
    }

您还可以使用元数据基础设施来解决这个问题,这为我们提供了一种更具表现力的区分服务的方式。


0
投票

这个问题提出已经有一段时间了,但我认为现在有一个更简单的解决方案。

您可以有条件地注册一个装饰器。不管“装饰器”是真的装饰器还是全新的实现

 builder.RegisterDecorator<ExecutableFilter, IFilter>(c => c.ImplementationType == typeof(DiversityFilter));

这样,具体类型“DiversityFilter”将替换为“ExecutableFilter”

© www.soinside.com 2019 - 2024. All rights reserved.