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

Ray*_*Ray 21 inversion-of-control simple-injector

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

see*_*per 23

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

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

public interface IFoo
{

}

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

    }
}
Run Code Online (Sandbox Code Playgroud)

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");
Run Code Online (Sandbox Code Playgroud)

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

public interface IBar { }

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

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

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

如果问题是关于将"静态"原始值传递给构造函数,那么只需通过注册这样的工厂委托来完成.

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

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

  • 一切都是好的.我只是不喜欢行container.Register <string,IFoo>((factory,value)=> new Foo(value)); 如果Foo有一些其他依赖项IService1,...,IServiceN应该由容器注入怎么办?我想说的是,只需对该特定参数使用某个字符串,其余参数容器应提供依赖关系.我怎么能做到这一点? (9认同)
  • 那么`container.Register&lt;IFoo&gt;((factory) =&gt; new Foo(container.GetInstance&lt;ISomeOtherDependency&gt;(), "SomeValue"));`? (3认同)

quj*_*jck 20

使用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)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

此处详细介绍了注入原始依赖项的高级选项


Lia*_*iam 7

如果您的构造函数没有任何其他依赖项(或者您想手动解决这些依赖项),则以上所有内容均适用。如果您遇到以下情况,但情况却有所下降:

public class Test : ITest
{
   private IFoo _foo;
   public Test(string parameter, IFoo foo)
   {
      _foo = foo;
      ....
   }
}
Run Code Online (Sandbox Code Playgroud)

现在,您不仅需要手动插入字符串,而且还需要手动插入字符串Foo。因此,现在(完全)您根本不使用依赖注入。同样是简单注入器状态:

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

我的理解是,他们说“不要这样做”。

可扩展性点

这里的另一种选择是针对这种情况使用“可扩展性点”

为此,您需要从注入的元素中提取硬编码元素:

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

  public void Init(string parameter)
  {

  }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以注入自己的附属对象硬编码的元素:

_container.Register<ITest, Test>();
_container.RegisterInitializer<Test>(instance => {instance.Init("MyValue");});
Run Code Online (Sandbox Code Playgroud)

如果现在添加另一个依赖关系,则注入现在可以进行,而无需更新配置,即代码仍然可以很好地解耦:

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

  }
}
Run Code Online (Sandbox Code Playgroud)