注入依赖项作为方法参数而不是构造函数参数

Inject dependency as method parameter instead of constructor parameter

我们可以使用 MEF 或 Autofac 将依赖项作为方法参数而不是构造函数参数注入吗?

谢谢

我不知道 MEF,因为我从未使用过它。你可以do it with Unity and with Autofac

团结

来自 MSFT 文档。

Unity instantiates dependent objects defined in parameters of methods that carry the InjectionMethod attribute within the scope of the target object. Then it calls the attributed method of the target object before returning the object to the caller. You must apply the InjectionMethod attribute in the target class to initiate method call injection.

public class MyObject
{
   public SomeOtherObject dependentObject;

  [InjectionMethod]
  public void Initialize(SomeOtherObject dep) 
  {
    // assign the dependent object to a class-level variable
    dependentObject = dep;
  }
}

这会将 class 标记为具有必须在实例化 class 时调用的依赖方法,并注入其方法参数。

IUnityContainer uContainer = new UnityContainer();
MyObject myInstance = uContainer.Resolve<MyObject>();

// access the dependent object
myInstance.dependentObject.SomeProperty = "Some value";

Autofac

Autofac 在服务激活期间通过 lambda 或回调来完成。来自 Autofac 文档

While constructor parameter injection is the preferred method of passing values to a component being constructed, you can also use property or method injection to provide values.

Property injection uses writeable properties rather than constructor parameters to perform injection. Method injection sets dependencies by calling a method.

// Register the type that you want to resolve with a resolution callback. Within the callback, invoke the method with a resolved dependency.
builder.Register(c => {
  var result = new MyObjectType();
  var dep = c.Resolve<TheDependency>();
  result.SetTheDependency(dep);
  return result;
});

另一种方法是注册回调。

builder
  .Register<MyObjectType>()
  .OnActivating(e => {
      var dep = e.Context.Resolve<TheDependency>();
      e.Instance.SetTheDependency(dep);
  });

两个框架都只能在解析时做方法注入。但是,您不能在实例化对象后将依赖项注入到方法中。在这些情况下,您应该使用工厂来获取您拥有的依赖项,让工厂通过您的 DI 容器解析它。

工厂

// Create the factory. The factory will have a static method that the DI system can register a lambda with, so that the factory can resolve through the DI container without being tightly coupled to it.
public class BarFactory
{
    private static Func<IBarDependency> internalFactory;

    public static void SetFactory(Func<IBarDependency> factory)
    {
        this.internalFactory = factory;
    }

    public IBarDependency CreateBar()
    {
        // Use the DI container lambda assigned in SetFactory to resolve the dependency.
        return internalFactory();
    }
}

public class DependencyInjectionBootstrap
{
    IContainer container;

    public void SetupDI()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<BarDependency>().As<IBarDependency>();
        container = builder.Build();

        // Tell the factory to resolve all IBarDependencies through our IContainer.
        BarFactory.SetFactory(() => container.Resolve<IBarDependency>());
    }
}

public class FooViewModel
{
    public void ExecuteSave()
    {
        var barFactory = new BarFactory();
        IBarDependency bar = barFactory.CreateBar();
    }
}