简体   繁体   English

按类型使用委托工厂进行Autofac Resolve

[英]Autofac Resolve using delegate factory by type

I am using Autofac for IoC in my project. 我在我的项目中将Autofac用于IoC。 Due to some legacy software libraries I must pass some services to the controller that can't be resolved, and must be passed as parameter. 由于某些旧版软件库,我必须将一些无法解析的服务传递给控制器​​,并且必须将其作为参数传递。

I've made a generic control using delegate factories like this: 我已经使用委托工厂进行了通用控制,如下所示:

public MyClass<TController, TInterface> {

     private delegate TController ControllerFactory(TInterface service);

     protected TController _myController;
     protected TController Controller {
         get
         {
             return _controller 
               ?? (_controller = ServiceLocator.Resolve<ControllerFactory>()
                                    .Invoke(this);
         }
     }

}

This works perfect, but for this to work I need the controller's service parameter name and the delegate service parameter name be the same, because as I have read, Autofac pairs the parameter BY NAME !! 这很完美,但是要使它正常工作,我需要控制器的服务参数名称和委托服务参数名称相同,因为正如我所读到的,Autofac将参数BY NAME配对!

I've seen you can do it by type registering the class with generic Func<>, but due to the legacy app I would need to leave "clean" registrations ie: 我已经看到您可以通过使用通用Func <>类型注册类来完成此操作,但是由于遗留应用程序,我需要保留“干净”注册,即:

containerBuilder.RegisterType<MyController>();

Does anyone know if it's possible to make the delegate match the parameter by type?? 有谁知道是否有可能使委托按类型匹配参数?

Does anyone know if it's possible to make the delegate match the parameter by type?? 有谁知道是否有可能使委托按类型匹配参数?

Yes, you can use predefined delegates. 是的,您可以使用预定义的委托。 See dynamic instantiation section here . 请参见此处的动态实例化部分。

Here's an quick example: 这是一个简单的例子:

    public class ComponentFactory
    {
        private readonly Func<Dependency, Component> _componentFactory;

        public ComponentFactory(Func<Dependency, Component> componentFactory)
        {
            _componentFactory = componentFactory;
        }

        public Component Create(Dependency dependency)
        {
            return _componentFactory(dependency);
        }
    }

    public class Component
    {
        private readonly Dependency _dependency;

        public Component(Dependency dependency)
        {
            _dependency = dependency;
        }
    }

    public class Dependency
    {
    }

Registration + Usage 注册+用法

            var builder= new ContainerBuilder();
            builder.RegisterType<ComponentFactory>();
            builder.RegisterType<Component>();
            builder.RegisterType<Dependency>();

            var container = builder.Build();
            var factory = container.Resolve<ComponentFactory>();

            //Usage with typed parameters
            var component = factory.Create(new Dependency());

**Be warned, if you use this method, Autofac throws an exception if you try to add parameters with of the same type. **请注意,如果您使用此方法,则尝试添加相同类型的参数时,Autofac会引发异常。 Ex. 例如 Component has two dependencies on Dependency Component有两个依赖Dependency

Exception looks something like this: 异常看起来像这样:

The input parameter type list has duplicate types. 输入参数类型列表具有重复的类型。 Try registering a custom delegate type instead of using a generic Func relationship. 尝试注册自定义委托类型,而不使用通用的Func关系。

Autofac is more specific about what type you register the controller as than most DI containers. 与大多数DI容器相比,Autofac更具体地说明了将控制器注册为哪种类型。 It will only resolve the type by its type if you include .AsSelf() in the registration of the controller. 仅当在控制器的注册中包含.AsSelf() ,才会按类型解析类型。 Here is a module we use in our project for registering MVC controllers. 这是我们在项目中用于注册MVC控制器的模块。

public class MvcModule
    : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        var currentAssembly = typeof(MvcModule).Assembly;

        builder.RegisterAssemblyTypes(currentAssembly)
            .Where(t => typeof(IController).IsAssignableFrom(t))
            .AsImplementedInterfaces()
            .AsSelf()
            .InstancePerDependency();
    }
}

Using this registration, you can resolve each controller by controller type. 使用此注册,可以按控制器类型解析每个控制器。

var type = typeof(HomeController);
var controller = container.Resolve(type);

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

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