gpt4 book ai didi

c# - 带有 Autofac.Extras.DynamicProxy2 的 Autofac 全局接口(interface)拦截器

转载 作者:太空狗 更新时间:2023-10-29 22:10:41 27 4
gpt4 key购买 nike

我在 Autofac DynamicProxy2 中使用接口(interface)拦截器,我能够为每个寄存器启用接口(interface)拦截器:

   var registration = builder.RegisterType<AType>().As<AInterface>();
registration.EnableInterfaceInterceptors().InterceptedBy<AInterceptor>()

我想将某些特性应用于所有已注册的类型。像这样的东西:

   var registrations = builder.GetAllRegistrations(); // ops, this does not exist...
foreach (var registration in registrations) {
registration.EnableInterfaceInterceptors().InterceptedBy<AInterceptor>()
}

我找不到获取所有注册的方法。我知道我们可以做到:

   builder.RegisterCallback(cr =>
{
foreach (var registration in cr.Registrations)
{
// registration is IComponentRegistration
}
});

但是这里的注册是一个IComponentRegistration,我需要一个IRegistrationBuilder来应用EnableInterfaceInterceptors()

最佳答案

您可以动态添加拦截器,但这需要一些工作。要走的路是创建一个自定义 Autofac.Module 附加到所有组件注册。我将在示例中向您展示。

您实际上不能在全局范围内执行 EnableInterfaceInterceptors我会在示例的末尾进行说明。

首先,示例设置:我们有一个简单的接口(interface)、一个简单的实现和一个将处理日志记录调用的拦截器。 (我正在窃取拦截器代码 from the Autofac wiki ):

public interface IInterface
{
void DoWork();
}

public class Implementation : IInterface
{
public void DoWork()
{
Console.WriteLine("Implementation doing work.");
}
}

public class CallLogger : IInterceptor
{
TextWriter _output;

public CallLogger(TextWriter output)
{
_output = output;
}

public void Intercept(IInvocation invocation)
{
_output.WriteLine("Calling method {0} with parameters {1}... ",
invocation.Method.Name,
string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray()));

invocation.Proceed();

_output.WriteLine("Done: result was {0}.", invocation.ReturnValue);
}
}

我们想用我们的调用记录器拦截一切(启用拦截器的)。我们通过创建一个自定义的 Autofac.Module 来实现,它都注册了拦截器本身Autofac 并动态附加到组件注册以添加拦截器元数据。

警告:这里有一些黑客攻击,但有点像将数据“戳”到某个已知位置。它有效,我不知道它为什么会改变,但请注意,因为它有点像在处理“私有(private)化”的东西,所以这可能会在未来的版本中中断。请注意。

好的,免责声明完成。这是模块:

public class InterceptorModule : Autofac.Module
{
// This is a private constant from the Autofac.Extras.DynamicProxy2 assembly
// that is needed to "poke" interceptors into registrations.
const string InterceptorsPropertyName = "Autofac.Extras.DynamicProxy2.RegistrationExtensions.InterceptorsPropertyName";

protected override void Load(ContainerBuilder builder)
{
// Register global interceptors here.
builder.Register(c => new CallLogger(Console.Out));
}

protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
// Here is where you define your "global interceptor list"
var interceptorServices = new Service[] { new TypedService(typeof(CallLogger)) };

// Append the global interceptors to any existing list, or create a new interceptor
// list if none are specified. Note this info will only be used by registrations
// that are set to have interceptors enabled. It'll be ignored by others.
object existing;
if (registration.Metadata.TryGetValue(InterceptorsPropertyName, out existing))
{
registration.Metadata[InterceptorsPropertyName] =
((IEnumerable<Service>)existing).Concat(interceptorServices).Distinct();
}
else
{
registration.Metadata.Add(InterceptorsPropertyName, interceptorServices);
}
}
}

为了使其工作,您需要将模块与其他依赖项一起注册。对于这个例子,它看起来像: var builder = new ContainerBuilder();

// Notice this registration doesn't include
// the interceptor - that gets added by the
// module.
builder.RegisterType<Implementation>()
.As<IInterface>()
.EnableInterfaceInterceptors();

// Here's the magic module:
builder.RegisterModule<InterceptorModule>();
var container = builder.Build();

如果您运行这些注册并解决...

var impl = container.Resolve<IInterface>();
impl.DoWork();

您可以看到拦截器工作,您将看到控制台输出:

Calling method DoWork with parameters ... 
Implementation doing work.
Done: result was .

(这有点奇怪,因为我的示例中有一个无参数/void 方法,但拦截器正在工作!)

至于EnableInterfaceInterceptors 调用... 执行EnableInterfaceInterceptorsEnableClassInterceptors 实际上做了很多疯狂的DynamicProxy2在后端工作。它将一些重要的事件处理程序添加到组件上的激活事件中,将对象包装在动态代理中。这些事件处理程序当前未公开供单独使用,我不确定尝试并“事后”附加所有这些东西需要多少工作,就像我们在这里使用实际拦截器所做的那样。

欢迎您亲自尝试 - the source is on GitHub .但是,基本上,虽然“添加一个全局拦截器”是有效的,但在模块中执行全局 EnableInterfaceInterceptors 却很不寻常。你肯定会独自一人。

关于c# - 带有 Autofac.Extras.DynamicProxy2 的 Autofac 全局接口(interface)拦截器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22782086/

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