autofac runtime-context based dependency injection

时间:2017-08-04 13:09:34

标签: c# asp.net-mvc inversion-of-control autofac

I am working on a NopCommerce Plugin, an opensource project which uses autofac and asp.net mvc 5 .

Let's say I have the following types

  1. an IService interface and two implementations AService and BService
  2. an IFactory with a method PrepareModel(Customer) and an implementantion Factory with a dependency to ISubFactory
  3. an ISubFactory and an implementantion SubFactory with a dependency to IService
  4. a Controller which should depend on IFactory

Lastly, I have a setting for each Customer object indicating whether AService or BService should be used.

What I need is to resolve IFactory and its dependencies dependencies and call Factory.PrepareModel(Customer) from within actions of the Controller.

public ActionResult Foo(Customer customer)
{
    ...
    IFactory factory = //use AService if customer.aService else BService
    var model = factory.PrepareModel(customer)
    ...
}

Some thoughts :

  1. I could pass around an instance of IContainer, however it is
    discouraged in the documentation of autofac.
  2. I can't delegate Factory because I am handling interfaces
  3. I could create an IServiceFactory with a method

    IService GetService(Customer customer);

    However, ISubFactory is not and should not be aware of the setting and thus the IServiceFactory can't be used.

Any other thoughts?

1 个答案:

答案 0 :(得分:0)

我的建议是指定一个可以将调用转发到正确的底层实现的代理。实现代理的最佳级别取决于您的设计和应用程序需求,但我猜您应该为ISubFactory指定代理。

以下代码段显示了ISubFactory的可能代理实现。

class DispatchingSubFactoryProxy : ISubFactory
{
    private readonly ISubFactory aFactory;
    private readonly ISubFactory bFactory;

    public DispatchingSubFactoryProxy(
        ISubFactory aFactory, ISubFactory bFactory)
    {
        this.aFactory = aFactory;
        this.bFactory = bFactory;
    }

    public Model PremareSubModel(Customer c) => GetFactory(c).PremareSubModel(c);
    ISubFactory GetFactory(Customer c) => c.aService ? aFactory : bFactory;
}

使用此DispatchingSubFactoryProxy,您可以创建以下注册以解决此问题:

container.RegisterType<ServiceA>().AsSelf();
container.RegisterType<ServiceB>().AsSelf();

container.Register<ISubFactory>(c =>
    new DispatchingSubFactoryProxy(
        aFactory: new SubFactory(c.Resolve<ServiceA>())
        bFactory: new SubFactory(c.Resolve<ServiceB>())));