[英]Factory Interface in Simple Injector
我是一個試圖學習 Simple Injector 的 Ninject 用戶
我在應用程序中經常使用的一個 Ninject 功能是工廠接口
有了它,我可以創建一個這樣的接口:
public interface IBarFactory
{
Bar CreateBar();
}
然后像這樣注冊
kernel.Bind<IBarFactory>().ToFactory();
然后我簡單的可以使用IBarFactory,而不必創建IBarFactory的實現
我現在嘗試在 Simple njector 中找到類似的東西,並找到了這個。 但是對於那個接近者,我必須實現工廠接口(更多代碼)。 如果 Bar 對象需要對另一個對象的引用,我該怎么辦?
Simple Injector 缺少這個工廠接口工具。 這種省略背后的想法是,當正確應用依賴注入時, 使用工廠的需要被最小化,這使得此類功能的有用性受到限制。
在 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 中,它就變成了一個基礎設施。
所以特意排除了這個特性,但是可以通過使用ResolveUnregisteredType
事件來擴展庫:
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>();
就是這樣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.