运行时Autofac通用服务解析

本文关键字:服务 Autofac 运行时 | 更新日期: 2023-09-27 18:18:20

最近,Castle添加了对由内核提供实现的接口工厂的支持。我想知道是否有一种方法来做到这一点在自动也。我已经了解了委托工厂,但我想我可能错过了一些东西,我无法让它工作。我是这么想的:

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();

谢谢,尼克

运行时Autofac通用服务解析

您可以通过创建一个具体的IHandlerFactory来隔离这种耦合,例如AutofacHandlerFactory,它将接收ILifetimeScope。这种耦合似乎是不可避免的,因为容器是唯一能够解决适当的IHandler<T>的容器。

ILifetimeScope的耦合可能是一个坏主意,但是,耦合在具体的IHandlerFactory内部是隔离的,Bus只是通过接口使用它。假设你改变了容器并开始使用Ninject,你可以实现一个NinjectHandlerFactory来完成这项工作。

看来答案是否定的。

我试过使用AggregateService,它应该做你想做的事情,但它在工厂解决时崩溃了,消息是"The type"Castle.Proxies。IComponentFactoryProxy" from assembly "DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"试图实现一个不可访问的接口。(原文是俄语,我已经翻译了)。

我想不出另一种没有手动(但相当简单)实现的方法。也许你应该写信给尼古拉斯·布卢姆哈特。

事实上,我最好这样做:

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耦合是一个坏主意。它是一个非常简单的接口,可以包装到你自己的实现中。或者您可以将代码分解到一个简单的工厂类中。好吧,看来你不需要我的建议就知道怎么做了。