简单注射器中的工厂接口

我是Ninject用户,试图学习Simple Injector

我经常在我的应用程序中使用的一个Ninject feture是Factory Interface

有了它,我可以创建一个这样的接口:

public interface IBarFactory { Bar CreateBar(); } 

并注册就像这样

 kernel.Bind().ToFactory(); 

然后我简单可以使用IBarFactory,而不必创建IBarFactory的实现

我现在尝试在Simple njector中找到类似的东西,并找到了这个 。 但是随着那个接近,我必须实现工厂接口(更多代码)。 如果Bar对象需要引用另一个对象,该怎么办?

Simple Injector缺少这种工厂接口设施。 这种省略背后的想法是,在正确应用dependency injection时, 最小化了使用工厂的需求 ,这使得这种function的有用性受到限制。

在Simple Injector中,你必须自己编写一个实现,但这通常是微不足道的。 例:

 private sealed class SimpleInjectorBarFactory : IBarFactory { private readonly Container container; public SimpleInjectorBarFactory(Container container) { this.container = container; } public Bar CreateBar() => this.container.GetInstance(); } 

这个类可以像这样注册:

 container.RegisterSingleton(); 

或者 – 如果你很懒 – 你可以注册一个Func注入如下:

 container.RegisterInstance>(() => container.GetInstance()); 

请注意,由于此SimpleInjectorBarFactory实现依赖于Container实例,因此它应该是Composition Root的一部分,以防止将Container用作服务定位器 。 通过将类放在组合根中,它只是一个基础结构 。

因此,故意排除该function,但可以使用有限数量的代码轻松扩展库以允许此function:

 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(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(); 

而已。