运行时Autofac通用服务解析

时间:2011-12-20 17:04:10

标签: c# autofac

最近,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();

谢谢, 尼克

2 个答案:

答案 0 :(得分:4)

似乎答案是'不'。

我尝试使用AggregateService本应该做你想要的,但它在工厂解析期间崩溃,消息'The type'Castle.Proxies.IComponentFactoryProxy“from assembly”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的耦合是一个坏主意。嗯,这是一个非常简单的界面,可能会包含在您自己的实现中。或者您可以将代码分解为简单的工厂类。好吧,似乎你知道如何在没有我的建议的情况下做到这一点。

答案 1 :(得分:4)

你可以通过创建一个具体的IHandlerFactory来隔离这种耦合,比如AutofacHandlerFactory,它会收到ILifetimeScope。这种耦合似乎是不可避免的,因为容器是唯一可以解析正确IHandler<T>的人。

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