gpt4 book ai didi

c# - 简单注入(inject)器中的工厂接口(interface)

转载 作者:IT王子 更新时间:2023-10-29 04:48:32 24 4
gpt4 key购买 nike

我是 Ninject 用户,正在尝试学习 Simple Injector

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

有了它我可以创建一个这样的界面:

public interface IBarFactory
{
Bar CreateBar();
}

然后像这样注册

kernel.Bind<IBarFactory>().ToFactory();

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

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

最佳答案

Simple Injector 缺少这种工厂接口(interface)设施。这个遗漏背后的想法是,当正确应用依赖注入(inject)时,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>注入(inject)如下:

container.RegisterInstance<Func<Bar>>(() => container.GetInstance<Bar>());

请注意,由于此 SimpleInjectorBarFactory实现取决于 Container例如,它应该是 Composition Root 的一部分以防止将容器用作 Service Locator .通过将这些类放在您的Composition Root 中,它就变成了一个piece of infrastructure。 .

因此特意排除了该功能,但可以通过使用 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>();

就是这样。

关于c# - 简单注入(inject)器中的工厂接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21905058/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com