【问题标题】:Autofac Generic Service resolution at runtime运行时 Autofac 通用服务解析
【发布时间】:2011-12-22 06:24:24
【问题描述】:

最近,Castle 通过内核提供的实现增加了对接口工厂的支持。我想知道是否也有办法在 autofac 中做到这一点。我已经阅读了有关委托工厂的信息,但我认为我可能遗漏了一些东西,并且无法使其正常工作。这是我的想法:

class Message { }

interface IHandle<T> {
    void Handle(T message);
}

class Handle<Message> : IHandle<Message> {
    ...
}

class Bus {
    .ctor (? lookup) {
        _lookup = lookup;
    }

    void Send<T>(T message) {
        _lookup.GetHandler<T>().Handle(message);
    }
}

var builder = new ContainerBuilder();
builder.RegisterType<Handle<Message>>().As<IHandle<Message>>();
builder.RegisterType<Bus>();

var container = builder.Build();
container.Resolve<Bus>().Send<Message>(new Message());

我想要做的是让容器远离总线(因为我同意服务定位器是一种反模式)或任何其他实现。如果我只是将容器提供给总线,或者创建一些包装容器的类工厂,这个问题很容易。只是想确保没有办法做到这一点。

顺便说一句,城堡之路iirc允许我注册这样的东西:

interface IHandlerFactory {
    IHandle<T> GetHandler<T>();
}

container.Register<IHandlerFactory>().AsFactory();

谢谢, 尼克

【问题讨论】:

  • Castle 方法看起来非常聪明——Autofac 不支持这一点。我认为@kcalvanti 下面的方法最适合这种情况,但是您也可以使用 Autofac 的 IIndex&lt;K,V&gt; 类型达到类似的效果,但需要更多配置。
  • @NicholasBlumhardt 是的,我现在要接受他的回答。如果以后有变化,我绝对可以重温。

标签: c# autofac


【解决方案1】:

您可以通过创建具体的IHandlerFactory 来隔离该耦合,例如AutofacHandlerFactory,它将接收ILifetimeScope。这种耦合似乎是不可避免的,因为容器是唯一可以解决正确IHandler&lt;T&gt; 的容器。

ILifetimeScope 耦合可能是个坏主意,但随后,耦合在具体IHandlerFactory 内部被隔离,Bus 只是通过接口使用它。假设您更改了容器并开始使用 Ninject,您只需实现 NinjectHandlerFactory 即可完成这项工作。

【讨论】:

  • 如果不存在复制城堡功能的功能,这肯定是要走的路(事实上我现在就是这样)。
【解决方案2】:

似乎答案是否定的。

我尝试使用 AggregateService,它应该可以满足您的需求,但它在工厂解析期间崩溃,并显示来自程序集“DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" 试图实现一个不可访问的接口。 (原文是俄语,我已经翻译了)。

如果没有手动(但非常简单)实现,我想不出另一种方法。也许你应该写信给 Nicholas Blumhardt。

其实我最好这样:

public class Bus {
  readonly ILifetimeScope _OwnScope;

  // Autofac always provides ILifetimeScope that owns a component as a service to the component
  // so it can be used as a dependency
  public Bus(ILifetimeScope ownScope) {
    _OwnScope = ownScope;
  }

  void Send<T>(T message) {
    _OwnScope.Resolve<IHandler<T>>.Handle(message);
  }
}

您可能会争辩说与ILifetimeScope 耦合是一个坏主意。嗯,这是一个非常简单的接口,可以包装到您自己的实现中。或者您可以将代码分解为一个简单的工厂类。好吧,如果没有我的建议,您似乎知道如何做到这一点。

【讨论】:

  • 我之前看到过有关聚合服务的信息,但看了一眼。我认为这肯定是要走的路。我同意,ILifetimeScope 是一个坏主意,因为它会将 autofac 泄漏到我不应该出现的项目中。带有 autofacimpl 的 IHandlerFactory 将是我不会太漏的方法。
  • @neouser99 是的,我只是希望它能奏效。如果您设法使其工作,请在设置上发布一些提示。也许我使用了一些错误的 Castle 程序集或其他什么。
猜你喜欢
  • 2012-11-22
  • 2018-08-31
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 2020-01-27
  • 2023-03-10
  • 1970-01-01
相关资源
最近更新 更多