如何使用Simple Injector将参数传递给构造函数?

时间:2014-02-14 17:30:55

标签: inversion-of-control simple-injector

Simple Injector允许您在解析时将参数传递给构造函数吗?我想知道这两个框架是否都可以执行Unity的ResolverOverride或DependencyOverride。

4 个答案:

答案 0 :(得分:22)

我怀疑这个问题是关于在实际解析服务时将原始值传递给构造函数。

让我们设置一个简单的测试类:

public interface IFoo
{

}

public class Foo : IFoo
{
    public Foo(string value)
    {

    }
}

Foo类接受我们想要在解析IFoo服务时提供的字符串参数。

var container = new ServiceContainer();
container.Register<string, IFoo>((factory, value) => new Foo(value));
var firstFoo = container.GetInstance<string, IFoo>("SomeValue");
var secondFoo = container.GetInstance<string, IFoo>("AnotherValue");

如果我们希望能够在不直接使用容器的情况下创建Foo类的新实例,我们可以简单地注入一个函数委托。

public interface IBar { }

public class Bar : IBar
{
    public Bar(Func<string, IFoo> fooFactory)
    {
        var firstFoo = fooFactory("SomeValue");
        var secondFoo = fooFactory("AnotherValue");
    }
}

“组合根”现在看起来像这样:

var container = new ServiceContainer();
container.Register<string, IFoo>((factory, value) => new Foo(value));
container.Register<IBar, Bar>();
var bar = container.GetInstance<IBar>();

如果问题是关于将“静态”原始值传递给构造函数,可以通过注册这样的工厂委托来完成。

var container = new ServiceContainer();
container.Register<IFoo>((factory) => new Foo("SomeValue"));
var firstInstance = container.GetInstance<IFoo>();
var secondInstance = container.GetInstance<IFoo>();

不同之处在于此方法不允许您在解决时传递值。该值在注册时静态指定。

答案 1 :(得分:18)

Simple Injector最简单的选择可能是向代表注册

[Test]
public void Test1()
{
    Container container = new Container();

    container.Register<IClassWithParameter>(() => new ClassWithParameter("SomeValue"));

    var result = container.GetInstance<IClassWithParameter>();
}

public interface IClassWithParameter { }

public class ClassWithParameter : IClassWithParameter
{
    public ClassWithParameter(string parameter)
    {
    }
}

注入原始依赖关系的高级选项详细here

答案 2 :(得分:3)

如果您的构造函数没有任何其他依赖项(或者您希望手动解析这些依赖项),则上述操作都可以正常工作。如果你有下面的情况虽然它下降了:

public class Test : ITest
{
   private IFoo _foo;
   public Test(string parameter, IFoo foo)
   {
      _foo = foo;
      ....
   }
}

现在,您不仅需要手动注入字符串,还需要Foo。所以现在你根本没有使用依赖注入(真的)。也是简单的注射器状态:

  

Simple Injector不允许注入原始类型(例如   整数和字符串)到构造函数。

我对此的解读是,他们说'不要这样做&#34;。

Extensibillity points

此处的另一个选择是使用"Extensibillity points" for this scenario

为此,您需要从注入的元素中抽象出硬编码元素:

public class Test : ITest
{
   private IFoo _foo;
   public Test(IFoo foo)
   {
      _foo = foo;
      ....
   }

  public void Init(string parameter)
  {

  }
}

您现在可以注入您的依赖项您的硬编码元素:

_container.Register<ITest, Test>();
_container.RegisterInitializer<Test>(instance => {instance.Init("MyValue");});

如果您现在添加另一个依赖项,您的注入现在可以在不必更新配置的情况下工作,即您的代码仍然很好地解耦:

public class Test : ITest
{
   private IFoo _foo;
   private IBar _bar;
   public Test(IFoo foo, IBar bar)
   {
      _foo = foo;
      _bar = bar;
      ....
   }

  public void Init(string parameter)
  {

  }
}

答案 3 :(得分:1)

针对利亚姆的回答,我想指出,有一种更简单的方法。

如果您遇到以下情况:

public class Test : ITest
{
   private IFoo _foo;
   public Test(IFoo foo, string parameter)
   {
      _foo = foo;
      ....
   }
}

您可以按如下方式编写ioc配置

_container.Register<IFoo, Foo>();
_container.Register<ITest>(
    () => new Test(
        _container.GetInstance<IFoo>(),
        "MyValue"
    )
);