简体   繁体   English

运行时Autofac通用服务解析

[英]Autofac Generic Service resolution at runtime

Recently, Castle added support for interface factories with implementations provided by the kernel. 最近,Castle通过内核提供的实现添加了对接口工厂的支持。 I am wondering if there is a way to do this in autofac also. 我想知道是否有办法在autofac中也这样做。 I have read about the delegate factories, but I think I might be missing something, and am unable to get it to work. 我已经阅读过有关代表工厂的信息,但我想我可能会遗漏一些东西,而且无法让它工作。 Here is what I am thinking: 这就是我的想法:

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

What I'm trying to do is keep the container out of the bus (as I agree that service locator is an anti-pattern) or any other implementation. 我要做的是将容器保持在总线之外(因为我同意服务定位器是反模式)或任何其他实现。 This problem is easy if I just feed the container to the bus, or create some class factory that wraps the container. 如果我只是将容器提供给总线,或者创建一个包装容器的类工厂,这个问题很容易。 Just trying to make sure there isn't a way to do this already. 只是想确保没有办法做到这一点。

Btw, the castle way iirc allows me to register something like this: 顺便说一句,城堡方式iirc允许我注册这样的东西:

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

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

Thanks, Nick 谢谢,尼克

Seems like the answer is 'No'. 似乎答案是“不”。

I've tried to use AggregateService which is supposed to do what you want, but it crashes during factory resolution with message 'The type "Castle.Proxies.IComponentFactoryProxy" from assembly "DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" has tried to implement an unaccessible interface.' 我已经尝试使用AggregateService本应该做你想要的,但它在工厂解析期间崩溃,消息'The type'Castle.Proxies.IComponentFactoryProxy“from assembly”DynamicProxyGenAssembly2,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null“试图实现一个无法访问的接口。” (The original message is in Russian, I've translated it). (最初的消息是俄语,我翻译了它)。

I can't figure out another approach that would work without a manual (yet quite simple) implementation. 我想不出另一种方法,如果没有手动(但非常简单)的实现,它将起作用。 Maybe you should write to Nicholas Blumhardt. 也许你应该写信给Nicholas Blumhardt。

In fact, I'd better do it this way: 事实上,我最好这样做:

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

You will probably argue that coupling with ILifetimeScope is a bad idea. 您可能会认为与ILifetimeScope耦合是一个坏主意。 Well, it's quite a simple interface which might be wrapped into your own implementation. 嗯,这是一个非常简单的界面,可能会包含在您自己的实现中。 Or you may factor the code out into a simple factory class. 或者您可以将代码分解为简单的工厂类。 Well, it seems like you know how to do this without my suggestions. 嗯,似乎你知道如何在没有我的建议的情况下做到这一点。

You could isolate that coupling by creating a concrete IHandlerFactory , say AutofacHandlerFactory , which would receive the ILifetimeScope . 您可以通过创建一个具体的IHandlerFactory来隔离该耦合,比如AutofacHandlerFactory ,它将接收ILifetimeScope That coupling seems inevitable since the container is the only one who can resolve the proper IHandler<T> . 这种耦合似乎是不可避免的,因为容器是唯一可以解析正确的IHandler<T>

Coupling with ILifetimeScope might be a bad idea, but then, the coupling is isolated inside the concrete IHandlerFactory , and the Bus just uses it through an interface. ILifetimeScope耦合可能是一个坏主意,但随后,耦合在具体的IHandlerFactory被隔离,而Bus只是通过接口使用它。 Let's say you change the container and starts using Ninject, you could just implement a NinjectHandlerFactory to do the job. 假设你改变了容器并开始使用Ninject,你可以实现一个NinjectHandlerFactory来完成这项工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM