我在我的项目中使用Simple Injector。对于与Castle.DynamicProxy集成Simple Injector,我使用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
答案 0 :(得分:2)
外部拦截器装饰第二个拦截器,因此当你调用invocation.InvocationTarget.GetType()
时,你可能得不到typeof(MyService)
,但类型变为Castle.Proxy.IMyServiceProxy
。这种类型显然没有声明属性,因此它返回null
。
老实说,我不知道如何解决这个问题,但这是我更喜欢使用SOLID代码并使用装饰器而不是使用拦截器的众多原因之一。
使用SOLID代码,问题完全消失,因为您的服务通常只有one method,这就不需要使用属性标记方法。当你这样做时,你的装饰者或拦截器只能应用于拦截界面的所有内容(因为它只有一个方法)而且你不必使用这样的属性。
如果您开始使用通用接口(例如ICommandHandler<T>抽象和IQueryHandler<T>抽象),则可以将装饰器应用于各种实现,从而无需编写拦截器。装饰器不需要依赖外部库,例如Castle Dynamic Proxy甚至是您的DI库,这使您的代码更加清晰4并且更易于维护。
答案 1 :(得分:0)
如上所述史蒂文,这段代码:
var method = invocation.GetConcreteMethod();
method = invocation.InvocationTarget.GetType().
GetMethod(method.Name);
获取代理类型的方法。
要获取实数类型的方法,可以使用MethodInvocationTarget属性:
method = invocation.MethodInvocationTarget;