gpt4 book ai didi

autofac - 如何使用 Autofac 注入(inject)同一对象的两个实例?

转载 作者:行者123 更新时间:2023-12-02 17:09:05 26 4
gpt4 key购买 nike

我正在使用 Autofac 构造函数注入(inject)。我需要弄清楚如何将单个对象实例注入(inject)多个构造函数参数,而不需要在容器设置阶段显式解析每个参数。

我有一个复杂的场景,可以通过这种行为来简化;以下示例只是一个简化的场景,因此我可以演示我正在寻找的行为。

示例:

假设我有这两个接口(interface),IOpenable 和 ICloseable:

public interface IOpenable
{
void Open();
}
public interface ICloseable
{
void Close();
}

我有这个 Door 类,它实现了它们:

public interface IDoor : IOpenable, ICloseable { }
public class Door : IDoor, IOpenable, ICloseable
{
void Open() { ... }
void Close() { ... }
}

我有一个接受 IOpenable 和 ICloseable 的类:

public class DoorHandler : IDoorHandler
{
public DoorHandler(IOpenable openable, ICloseable closeable)
{
...
}
...
}

问题:

每当 IOpenable 和 ICloseable 都是同一个构造函数中的依赖项时,是否可以告诉 autofac 将相同 Door 对象注入(inject)到两个参数中?

注意:我做不到:

container.Register<IDoorHandler>( c => {
Door d = c.Resolve<IDoor>();
return new DoorHandler(d,d)
});

做我想要的事情,但请记住,这个 DoorHandler 类只是一个示例。在我的真实代码中,“DoorHandler”实际上是一个 MVC Controller ,我使用 RegisterControllers() 注册它。所以我无法像上面那样注册它。此外,有时依赖关系图可能会变得过于复杂,并且在每种情况下显式执行此操作可能会变得难以承受。

我想我正在寻找的是能够做类似的事情:

container.RegisterType<DoorHandler>().As<IDoorHandler>();
container.RegisterType<Door>().As<IDoor>();
container.Register<IOpenable>( c => c.ResolveShared<IDoor>(); );
container.Register<ICloseable>( c => c.ResolveShared<IDoor>(); );

哪里可以调用 c.ResolveShared<T>如果在同一个构造函数中调用多个参数,则全部解析为同一个 T 对象。

或者也许:

container.RegisterType<DoorHandler>().As<IDoorHandler>();
container.RegisterType<Door>().As<IDoor>().InstancePerDependencyShared();
container.Register<IOpenable>( c => c.Resolve<IDoor>(); );
container.Register<ICloseable>( c => c.Resolve<IDoor>(); );

显然,如果我对 Door 对象使用 InstancePerLifetimeScope 或其他东西,则每个解析的 Door 将是相同的实例。但我不希望这样,我希望每次创建 DoorHandler 时都有一个 DoorHandler 的新实例,并且我希望该 Door 作为两个参数传递给 DoorHandler 构造函数。

最佳答案

好吧,有点棘手:) ...这是广义“每个构造函数”共享的一种可能的解决方案:

builder.RegisterControllers(asm)        
.OnPreparing(e => {
var spr = new SharedConstructorParameter(
typeof(IOpenable),
typeof(ICloseable));
e.Parameters = new Parameter[]{ spr }.Concat(e.Parameters);
});

需要在 OnPreparing() 事件中设置该参数,因为 SharedConstructorParameter 实例将缓存每个解析操作的值。

class SharedConstructorParameter : Parameter
{
object _cachedInstance;
Type[] _sharedParameterTypes;

public SharedConstructorParameter(params Type[] sharedParameterTypes)
{
_sharedParameterTypes = sharedParameterTypes;
}

protected override bool CanSupplyValue(
ParameterInfo pi,
IComponentContext cc,
out Func<object> valueCreator)
{
valueCreator = null;
if (!_sharedParameterTypes.Contains(pi.ParameterType))
return false;

valueCreator = () => {
_cachedInstance = _cachedInstance ?? cc.Resolve(pi.ParameterType);
return cachedInstance;
};
return true;
}
}

由您来编译和调试;)

关于autofac - 如何使用 Autofac 注入(inject)同一对象的两个实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5421803/

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