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

时间:2015-07-12 18:18:56

标签: c# dependency-injection mef autofac

我们可以使用MEF或Autofac?

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

由于

1 个答案:

答案 0 :(得分:3)

我不了解MEF,因为我从未使用它。您可以do it with Unitywith Autofac

统一

来自MSFT文档。

  

Unity实例化在目标对象范围内携带InjectionMethod属性的方法的参数中定义的依赖对象。然后在将对象返回给调用者之前调用目标对象的属性方法。必须在目标类中应用InjectionMethod属性才能启动方法调用注入。

public class MyObject
{
   public SomeOtherObject dependentObject;

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

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

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

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

Autofac

Autofac在激活服务期间通过lambdas或回调执行此操作。来自Autofac文档

  

虽然构造函数参数注入是将值传递给正在构造的组件的首选方法,但您也可以使用属性或方法注入来提供值。

     

属性注入使用可写属性而不是构造函数参数来执行注入。方法注入通过调用方法来设置依赖关系。

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