团结汽车工厂与params

我正在试图找出正确的方法来注入一个需要参数的自动工厂,或者即使Unity可以实现这一点。

例如,我知道我可以这样做:

public class TestLog { private Func logFactory; public TestLog(Func logFactory) { this.logFactory = logFactory; } public ILog CreateLog() { return logFactory(); } } Container.RegisterType(); TestLog test = Container.Resolve(); ILog log = test.CreateLog(); 

现在我希望能做的是:

 public class TestLog { private Func logFactory; public TestLog(Func logFactory) { this.logFactory = logFactory; } public ILog CreateLog(string name) { return logFactory(name); } } Container.RegisterType(); TestLog test = Container.Resolve(); ILog log = test.CreateLog("Test Name"); 

不幸的是,这不起作用。 我可以看到你如何设置自定义工厂来在Unity中创建实例,似乎无法为这个例子提供任何明确的例子。

显然,我可以创建自己的工厂,但我正在寻找一种优雅的方式在Unity中以最少的代码执行此操作。

很抱歉成为那些讨厌回答自己问题的人之一,但我想出来了。

 public class TestLog { private Func logFactory; public TestLog(Func logFactory) { this.logFactory = logFactory; } public ILog CreateLog(string name) { return logFactory(name); } } Container.RegisterType>( new InjectionFactory(c => new Func(name => new Log(name)) )); TestLog test = Container.Resolve(); ILog log = test.CreateLog("Test Name"); 

@TheCodeKing的答案工作正常,但在大多数(可能全部?)案例中可以缩短为以下内容:

 Container.RegisterInstance>(name => new Log(name)); 

(注意我正在使用RegisterInstance()而不是RegisterType()

由于Func<>实现已经是一种工厂,因此通常不需要将它包装在InjectionFactory 。 它只能确保Func每个分辨率都是一个新实例,我真的不能想到需要这个的场景。

如果您正在寻找完全类型的工厂接口(例如,允许XML文档和参数名称),您可以使用我创建的NuGet包 ,您可以通过为工厂定义接口,然后关联它来利用它它与您想要实例化的具体类型。

代码存在于GitHub中: https : //github.com/PombeirP/FactoryGenerator

Autofac具有参数化实例化,以处理需要带参数的自动出厂的场景。

虽然Unity不支持开箱即用,但可以实现一个类似于Autofac的扩展。

一个无耻的插件:我实现了这样的扩展 – 参数化自动工厂 。
它可以以类似于此的方式使用:

 public class Log { public void Info(string info) { /* ... */ } public void Warn(string info) { /* ... */ } public void Error(string info) { /* ... */ } } public class LogConsumer { private readonly Log _log; private readonly string _consumerName; public LogConsumer(Log log, string consumerName) { _log = log; _consumerName = consumerName; } public void Frobnicate() => _log.Info($"{nameof(Frobnicate)} called on {_consumerName}"); } var container = new UnityContainer() .AddNewExtension(); var logConsumerFactory = container.Resolve>(); var gadget = logConsumerFactory("Gadget"); gadget.Frobnicate(); 

请注意:

  • Func是从container解析的,但它没有在任何地方注册 – 它是自动生成的。
  • Func仅为LogConsumer的构造函数提供string consumerName参数。 因此,从容器中解析Log log参数。 如果auto-factory func看起来像这个Func ,那么LogConsumer的构造函数的所有参数都将通过自动工厂提供。

基本上,扩展程序的工作方式如下:

  1. 它在Unity的管道中注册了一个所谓的BuilderStrategy
  2. 只要Unity要构建类型的实例,就会调用此策略。
  3. 如果要构建的类型尚未明确注册并且是带参数的Func ,则扩展将拦截实例构建过程。
  4. 现在我们只需要动态创建给定类型的Func ,它从容器中解析其返回类型,并将Func的参数作为ResolverOverride集合传递给IUnityContainer.Resolve方法。