Castle.DynamicProxy 和 Simple Injector 基于属性的拦截
Attribute based interception with Castle.DynamicProxy and Simple Injector
我在我的项目中使用了 Simple Injector。为了将 Simple Injector 与 Castle.DynamicProxy 集成,我正在使用 this example.
我有以下属性:
public class MyLogAttribute : Attribute { // some code. }
public class MyTimerAttribute : Attribute { // some code. }
然后这些属性应用于我的服务中的方法。
public interface IMyService
{
void Do();
}
public class MyService : IMyService
{
[MyLog, MyTimer]
public void Do() { // some code. }
}
在我的拦截器中,我尝试使用以下代码获取应用于方法的自定义属性:
public class MyLogIntercept : Castle.DynamicProxy.IInterceptor
{
public void Intercept(Castle.DynamicProxy.IInvocation invocation)
{
var method = invocation.GetConcreteMethod();
method = invocation.InvocationTarget.GetType().
GetMethod(method.Name);
var attribute = method.GetCustomAttribute<MyLogAttribute>();
if(attribute != null)
{
// some code.
}
else
invocation.Proceed();
}
}
public class MyTimerIntercept : Castle.DynamicProxy.IInterceptor
{
public void Intercept(Castle.DynamicProxy.IInvocation invocation)
{
var method = invocation.GetConcreteMethod();
method = invocation.InvocationTarget.GetType().
GetMethod(method.Name);
var attribute = method.GetCustomAttribute<MyTimerAttribute>();
if(attribute != null)
{
// some code.
}
else
invocation.Proceed();
}
}
这些拦截器使用以下代码注册:
container.InterceptWith<MyLogIntercept>(
type => type == typeof(IMyService));
container.InterceptWith<MyTimerIntercept>(
type => type == typeof(IMyService));
我的问题是,当我在 Intercept()
方法中尝试获取自定义属性时,我得到 null
(attribute == null
)。我怎样才能获得我的自定义属性?
P.S。如果为我的服务注册了一个拦截(MyTimerIntercept
或MyLogIntercept
它不符合),在Intercept()
方法中我可以获得自定义属性成功(attribute != null
),但是如果两个拦截器都注册了我有问题(attribute == null
)。
P.S。我正在使用 Castle.Core 3.3.3
外层拦截器装饰了第二个拦截器,所以当你调用invocation.InvocationTarget.GetType()
时,你可能得不到typeof(MyService)
,但类型变成了Castle.Proxy.IMyServiceProxy
。这种类型显然没有声明属性,所以这就是为什么它 returns null
.
老实说,我不知道如何解决这个问题,但这是我更喜欢使用 SOLID 代码并使用装饰器而不是使用拦截器的众多原因之一。
使用 SOLID 代码,问题就完全消失了,因为您的服务通常只有 one method,这消除了使用属性标记方法的需要。当你这样做时,你的装饰器或拦截器可以只应用于拦截接口的所有内容(因为它只有一个方法)并且你不必像这样搞砸属性。
如果您开始使用通用接口(例如 ICommandHandler<T> abstraction and IQueryHandler<T> 抽象),则可以将装饰器应用于广泛的实现,从而无需编写拦截器。装饰器消除了依赖外部库(例如 Castle Dynamic Proxy 甚至您的 DI 库)的需要,这使您的代码更加简洁且更易于维护。
正如史蒂文上面所写,这段代码:
var method = invocation.GetConcreteMethod();
method = invocation.InvocationTarget.GetType().
GetMethod(method.Name);
获取代理类型的方法。
获取real类型的方法,可以使用MethodInvocationTarget 属性:
method = invocation.MethodInvocationTarget;
我在我的项目中使用了 Simple Injector。为了将 Simple Injector 与 Castle.DynamicProxy 集成,我正在使用 this example.
我有以下属性:
public class MyLogAttribute : Attribute { // some code. }
public class MyTimerAttribute : Attribute { // some code. }
然后这些属性应用于我的服务中的方法。
public interface IMyService
{
void Do();
}
public class MyService : IMyService
{
[MyLog, MyTimer]
public void Do() { // some code. }
}
在我的拦截器中,我尝试使用以下代码获取应用于方法的自定义属性:
public class MyLogIntercept : Castle.DynamicProxy.IInterceptor
{
public void Intercept(Castle.DynamicProxy.IInvocation invocation)
{
var method = invocation.GetConcreteMethod();
method = invocation.InvocationTarget.GetType().
GetMethod(method.Name);
var attribute = method.GetCustomAttribute<MyLogAttribute>();
if(attribute != null)
{
// some code.
}
else
invocation.Proceed();
}
}
public class MyTimerIntercept : Castle.DynamicProxy.IInterceptor
{
public void Intercept(Castle.DynamicProxy.IInvocation invocation)
{
var method = invocation.GetConcreteMethod();
method = invocation.InvocationTarget.GetType().
GetMethod(method.Name);
var attribute = method.GetCustomAttribute<MyTimerAttribute>();
if(attribute != null)
{
// some code.
}
else
invocation.Proceed();
}
}
这些拦截器使用以下代码注册:
container.InterceptWith<MyLogIntercept>(
type => type == typeof(IMyService));
container.InterceptWith<MyTimerIntercept>(
type => type == typeof(IMyService));
我的问题是,当我在 Intercept()
方法中尝试获取自定义属性时,我得到 null
(attribute == null
)。我怎样才能获得我的自定义属性?
P.S。如果为我的服务注册了一个拦截(MyTimerIntercept
或MyLogIntercept
它不符合),在Intercept()
方法中我可以获得自定义属性成功(attribute != null
),但是如果两个拦截器都注册了我有问题(attribute == null
)。
P.S。我正在使用 Castle.Core 3.3.3
外层拦截器装饰了第二个拦截器,所以当你调用invocation.InvocationTarget.GetType()
时,你可能得不到typeof(MyService)
,但类型变成了Castle.Proxy.IMyServiceProxy
。这种类型显然没有声明属性,所以这就是为什么它 returns null
.
老实说,我不知道如何解决这个问题,但这是我更喜欢使用 SOLID 代码并使用装饰器而不是使用拦截器的众多原因之一。
使用 SOLID 代码,问题就完全消失了,因为您的服务通常只有 one method,这消除了使用属性标记方法的需要。当你这样做时,你的装饰器或拦截器可以只应用于拦截接口的所有内容(因为它只有一个方法)并且你不必像这样搞砸属性。
如果您开始使用通用接口(例如 ICommandHandler<T> abstraction and IQueryHandler<T> 抽象),则可以将装饰器应用于广泛的实现,从而无需编写拦截器。装饰器消除了依赖外部库(例如 Castle Dynamic Proxy 甚至您的 DI 库)的需要,这使您的代码更加简洁且更易于维护。
正如史蒂文上面所写,这段代码:
var method = invocation.GetConcreteMethod();
method = invocation.InvocationTarget.GetType().
GetMethod(method.Name);
获取代理类型的方法。
获取real类型的方法,可以使用MethodInvocationTarget 属性:
method = invocation.MethodInvocationTarget;