Castle Windsor Interceptors - get Target already in the ctor

Castle Windsor Interceptors - get Target already in the ctor

当我在 Castle Windsor 中使用拦截器时,只要调用函数(IInvocation 类型的调用参数),我就可以访问调用目标。

是否可以在这个拦截器的构造函数中已经获取到拦截器的目标,这样我就可以编写如下代码:

public class MyInterceptor: IInterceptor
{
   public MyInterceptor(ITargetOfInterception target, ILogger logger) 
   { 
       logger.Log("Interceptor created for target type: " + target.GetType() );
   }
}

您应该已经拥有您的实例...

container.Register(Component.For<IInterceptor>().ImplementedBy<Logger>().Named("myinterceptor"));

然后每个 class 你将用你的拦截器装饰一个属性。

[Interceptor("myinterceptor")]
public class Logger : IInterceptor 
{
    public void Intercept(IInvocation invocation) {
        Console.WriteLine(">> type in <<");
        invocation.Proceed();
        Console.WriteLine(">> type out <<");
    }    
}

如果您实施拦截器,您将能够知道解决了哪种类型,因为您已经定义了此类横切关注点以由拦截器解决。

我认为您想让您的拦截器知道所有需要与拦截器签订合同的类型,而不是所有绑定到拦截器指令的类型。希望对您有所帮助!!

编辑:这就是我使用 Unity 记录器的方式:

    Public Class LoggingInterceptionBehavior
        Implements IInterceptionBehavior
        Public Function Invoke(input As IMethodInvocation, getNext As GetNextInterceptionBehaviorDelegate) As IMethodReturn Implements IInterceptionBehavior.Invoke
            ' Before invoking the method on the original target. 
            Dim icp As ClaimsPrincipal = TryCast(Thread.CurrentPrincipal, ClaimsPrincipal)

            ' Access IClaimsIdentity which contains claims
            Dim claimsIdentity As ClaimsIdentity = DirectCast(icp.Identity, ClaimsIdentity)
            Dim param = GetParam(input)

            If claimsIdentity IsNot Nothing Then
                If param IsNot Nothing Then
                    WriteLog([String].Format("{0} is invoking method {1} at {2} with a parameter of {3}", claimsIdentity.Name, input.MethodBase, DateTime.Now.ToLongTimeString(), param))
                Else
                    WriteLog([String].Format("{0} is invoking method {1} at {2} without a parameter", claimsIdentity.Name, input.MethodBase, DateTime.Now.ToLongTimeString()))
                End If

            Else
                'no claim
                WriteLog([String].Format("NO CLAIM Invoking method {0} at {1} with a parameter of {2}", input.MethodBase, DateTime.Now.ToLongTimeString(), param))
            End If

            ' Invoke the next behavior in the chain.
            Dim result = getNext()(input, getNext)

            ' After invoking the method on the original target.
            If result.Exception IsNot Nothing Then
                WriteCriticalLog([String].Format("Method {0} threw exception {1} at {2}", input.MethodBase, result.Exception.Message, DateTime.Now.ToLongTimeString()))
            Else
                WriteLog([String].Format("Method {0} returned {1} at {2}", input.MethodBase, result.ReturnValue, DateTime.Now.ToLongTimeString()))
            End If

            Return result
        End Function

End Class

我如何注册它们:

    container.RegisterType(Of IXXXService, XXXService)(New Interceptor(Of InterfaceInterceptor)(),
                                                                 New InterceptionBehavior(Of LoggingInterceptionBehavior))

虽然我不知道你为什么需要它,但我可以想到 2 种可能的解决方案。

首先,您可以挂钩 container.ComponentRegistered 事件 (or some other event of your choosing),并检查处理程序以查看拦截器。

其次,您可以在拦截器中使用一些静态散列 table,并在拦截器检测到 "new" 目标时进行记录。

可能第一个方案就是你想要的。

无法在构造函数中访问目标,但您可以通过实现 IOnBehalfAware (see doco here)

来实现您的目标
public void SetInterceptedComponentModel(ComponentModel target)
{
    logger.Log("Interceptor created for target: " + target.ToString());
}