我正在试图找出注入自动工厂的正确方法,该工厂需要使用参数,或者即使Unity可以实现这一点。
例如,我知道我可以这样做:
public class TestLog
{
private Func<ILog> logFactory;
public TestLog(Func<ILog> logFactory)
{
this.logFactory = logFactory;
}
public ILog CreateLog()
{
return logFactory();
}
}
Container.RegisterType<ILog, Log>();
TestLog test = Container.Resolve<TestLog>();
ILog log = test.CreateLog();
现在我希望能做的是:
public class TestLog
{
private Func<string, ILog> logFactory;
public TestLog(Func<string, ILog> logFactory)
{
this.logFactory = logFactory;
}
public ILog CreateLog(string name)
{
return logFactory(name);
}
}
Container.RegisterType<ILog, Log>();
TestLog test = Container.Resolve<TestLog>();
ILog log = test.CreateLog("Test Name");
不幸的是,这不起作用。我可以看到你如何设置自定义工厂来在Unity中创建实例,似乎无法为这个例子提供任何明确的例子。
显然我可以创建自己的工厂,但我正在寻找一种优雅的方式在Unity中以最少的代码执行此操作。
答案 0 :(得分:30)
很抱歉成为那些讨厌回答自己问题的人之一,但我想出来了。
public class TestLog
{
private Func<string, ILog> logFactory;
public TestLog(Func<string, ILog> logFactory)
{
this.logFactory = logFactory;
}
public ILog CreateLog(string name)
{
return logFactory(name);
}
}
Container.RegisterType<Func<string, ILog>>(
new InjectionFactory(c =>
new Func<string, ILog>(name => new Log(name))
));
TestLog test = Container.Resolve<TestLog>();
ILog log = test.CreateLog("Test Name");
答案 1 :(得分:1)
如果您正在寻找完全类型的工厂界面(例如,允许使用XML文档和参数名称),您可以使用我创建的NuGet package,您只需通过定义接口即可工厂,然后将其与您想要实例化的具体类型相关联。
代码存在于GitHub中:https://github.com/PombeirP/FactoryGenerator
答案 2 :(得分:1)
Autofac有parameterized instantiation来处理需要带参数的自动出厂的方案。
虽然Unity不支持开箱即用,但可以实现与Autofac类似的扩展方式。
一个无耻的插件:我实施了这样的扩展 - Parameterized Auto Factory 它可以用类似的方式使用:
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<UnityParameterizedAutoFactoryExtension>();
var logConsumerFactory = container.Resolve<Func<string, LogConsumer>>();
var gadget = logConsumerFactory("Gadget");
gadget.Frobnicate();
请注意:
Func<string, LogConsumer>
已从container
解析,但未在任何地方注册 - 它会自动生成。 Func<string, LogConsumer>
仅向string consumerName
的构造函数提供LogConsumer
参数。因此,从容器中解析Log log
参数。如果auto-factory func看起来像这个Func<string, Log, LogConsumer>
,那么LogConsumer
的构造函数的所有参数都将通过自动工厂提供。 基本上,扩展程序的工作原理如下:
BuilderStrategy
。Func
,则扩展会拦截实例构建过程。Func
,从容器中解析其返回类型,并将Func
的参数作为ResolverOverride
集合传递给{ {1}}方法。