我是Ninject用户,试图学习Simple Injector
我经常在我的应用程序中使用的一个Ninject项目是Factory Interface
有了这个,我可以创建一个这样的界面:
public interface IBarFactory
{
Bar CreateBar();
}
就像这样的注册
kernel.Bind<IBarFactory>().ToFactory();
然后我简单可以使用IBarFactory,而不必创建IBarFactory的实现
我现在尝试在Simple njector中找到类似的东西,并找到this。 但是随着那个接近,我必须实现工厂接口(更多代码)。如果Bar对象需要引用另一个对象,该怎么办?
答案 0 :(得分:27)
Simple Injector缺少这个工厂接口设施。这个省略背后的想法是,正确应用依赖注入时,the need for using factories is minimized,这使得这种功能的有用性受到限制。
在Simple Injector中,你必须自己编写一个实现,但这通常是微不足道的。例如:
private sealed class SimpleInjectorBarFactory : IBarFactory {
private readonly Container container;
public SimpleInjectorBarFactory(Container container) {
this.container = container;
}
public Bar CreateBar() =>
this.container.GetInstance<Bar>();
}
这个类可以像这样注册:
container.RegisterSingleton<IBarFactory, SimpleInjectorBarFactory>();
或者 - 如果你很懒 - 你可以注册Func<Bar>
注册如下:
container.RegisterInstance<Func<Bar>>(() => container.GetInstance<Bar>());
请注意,由于此SimpleInjectorBarFactory
实施取决于Container
实例,因此它应该是Composition Root的一部分,以防止将Container用作Service Locator。通过将类放在 Composition Root 中,它变为piece of infrastructure。
因此故意排除该功能,但是可以使用有限的代码轻松扩展库以允许此功能:
using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
public static class AutomaticFactoryExtensions {
public static void RegisterFactory<TFactory>(this Container container) {
if (!typeof(TFactory).IsInterface)
throw new ArgumentException(typeof(TFactory).Name + " is no interface");
container.ResolveUnregisteredType += (s, e) => {
if (e.UnregisteredServiceType == typeof(TFactory)) {
e.Register(Expression.Constant(
value: CreateFactory(typeof(TFactory), container),
type: typeof(TFactory)));
}
};
}
private static object CreateFactory(Type factoryType, Container container) {
var proxy = new AutomaticFactoryProxy(factoryType, container);
return proxy.GetTransparentProxy();
}
private sealed class AutomaticFactoryProxy : RealProxy {
private readonly Type factoryType;
private readonly Container container;
public AutomaticFactoryProxy(Type factoryType, Container container)
: base(factoryType) {
this.factoryType = factoryType;
this.container = container;
}
public override IMessage Invoke(IMessage msg) {
if (msg is IMethodCallMessage) {
return this.InvokeFactory(msg as IMethodCallMessage);
}
return msg;
}
private IMessage InvokeFactory(IMethodCallMessage msg) {
if (msg.MethodName == "GetType")
return new ReturnMessage(this.factoryType, null, 0, null, msg);
if (msg.MethodName == "ToString")
return new ReturnMessage(this.factoryType.Name, null, 0, null, msg);
var method = (MethodInfo)msg.MethodBase;
object instance = this.container.GetInstance(method.ReturnType);
return new ReturnMessage(instance, null, 0, null, msg);
}
}
}
使用上面的扩展方法,您可以以与Ninject注册非常类似的方式进行工厂注册:
container.RegisterFactory<IBarFactory>();
就是这样。