简体   繁体   中英

Autofac Resolve using delegate factory by type

I am using Autofac for IoC in my project. 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 !!

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:

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. Ex. Component has two dependencies on 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.

Autofac is more specific about what type you register the controller as than most DI containers. It will only resolve the type by its type if you include .AsSelf() in the registration of the controller. Here is a module we use in our project for registering MVC controllers.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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