gpt4 book ai didi

c# - Autofac 委托(delegate)工厂可以将参数传递给嵌套对象吗?

转载 作者:行者123 更新时间:2023-12-03 23:25:04 28 4
gpt4 key购买 nike

我想使用 Autofac 委托(delegate)工厂来解析对象图,其中一些嵌套对象需要传递参数。例如。如果 Autofac delegate factory example 中的 QuoteService需要一个 url 来从中检索数据,或者 QuoteService 本身具有需要参数的依赖项。

public class WebQuoteService : IQuoteService
{
public WebQuoteService(Uri source)
{
}
}

public class Shareholding
{
public Shareholding(string symbol, uint holding, IQuoteService quoteService)
{
}
}

我希望能够像这样声明和注册一个委托(delegate):
public delegate Owned<Shareholding> ShareholdingFactory(string symbol, uint holding,
Uri source);
builder.RegisterGeneratedFactory<ShareholdingFactory>();

我遇到的问题是 Autofac 无法解析 WebQuoteService 的 uri 参数。

我见过一些类似的问题和解决方案,但没有什么特别整洁的。 Autofac-passing-parameter-to-nested-types建议注册一个 lambda 以显式实现工厂并解决嵌套依赖项。我确信这会起作用,但如果在更深层次上需要参数或有更多依赖项时,它会变得非常困惑。

我正在使用的临时解决方案对此进行了改进,解决了股权中的 IQuoteService OnPreparing , 并转发 Autofac 生成工厂创建的参数。
 builder.RegisterType<Shareholding>().OnPreparing(e =>
{
e.Parameters = e.Parameters.Union(new[]
{
new TypedParameter(typeof (IQuoteService), e.Context.Resolve<IQuoteService>(e.Parameters))
});
});

这可以正常工作并且避免手动解析其他参数,但我实际上需要执行两次才能将参数转发到第二个嵌套级别。

我考虑过,但没有尝试使用 BeginLifetimeScope(Action<ContainerBuilder>)根据 can-components-be-temporarily-registered-in-an-autofac-container 的建议.我想我必须手动实现工厂,但我可以注册 uri,这样它就可以在任何嵌套级别上工作。

我真正想做的是附加到 WebQuoteService OnPreparing 并访问委托(delegate)工厂的参数。可以使这样的东西与反射一起工作,但这显然并不理想。
builder.RegisterType<WebQuoteService>().OnPreparing(e =>
{
var parameters = e.Context._context._activationStack.Last().Parameters;
e.Parameters = e.Parameters.Concat(parameters);
});

谁能建议一种更简洁的替代方法来将参数传递给嵌套两层的对象?

最佳答案

很抱歉自我回答,但没有更好的建议,我认为我应该记录我拥有的最佳解决方案。

在 OnPreparing 中,您可以使用反射来访问 Autofac 激活堆栈和传递给委托(delegate)工厂的参数。然后可以将这些添加到正在解析的嵌套组件的参数中。这适用于任何级别的嵌套(只需要为需要参数的组件添加到 OnPreparing 即可。)

像这样注册:

builder.RegisterType<WebQuoteService>()
.OnPreparing(AutofacExtensions.ForwardFactoryParameters);

使用这个助手类:
public static class AutofacExtensions
{
private static readonly FieldInfo ContextFieldInfo;
private static readonly FieldInfo ActivationStackFieldInfo;

static AutofacExtensions()
{
var autofacAssembly = typeof(IInstanceLookup).Assembly;
Type instanceLookupType = autofacAssembly.GetType("Autofac.Core.Resolving.InstanceLookup");
ContextFieldInfo = instanceLookupType.GetField("_context", BindingFlags.Instance | BindingFlags.NonPublic);
Type resolveOperationType = autofacAssembly.GetType("Autofac.Core.Resolving.ResolveOperation");
ActivationStackFieldInfo = resolveOperationType.GetField("_activationStack", BindingFlags.Instance | BindingFlags.NonPublic);
}

public static IResolveOperation Context(this IInstanceLookup instanceLookup)
{
return (IResolveOperation)ContextFieldInfo.GetValue(instanceLookup);
}

public static IEnumerable<IInstanceLookup> ActivationStack(this IResolveOperation resolveOperation)
{
return (IEnumerable<IInstanceLookup>)ActivationStackFieldInfo.GetValue(resolveOperation);
}

/// <summary>
/// Pass parameters from the top level resolve operation (typically a delegate factory call)
/// to a nested component activation.
/// </summary>
public static void ForwardFactoryParameters(PreparingEventArgs e)
{
var delegateFactoryActivation = ((IInstanceLookup) e.Context).Context().ActivationStack().Last();
e.Parameters = e.Parameters.Concat(delegateFactoryActivation.Parameters);
}
}

关于c# - Autofac 委托(delegate)工厂可以将参数传递给嵌套对象吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27497640/

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