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());
}
当我在 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());
}