使用Castle.DynamicProxy和Simple Injector进行基于属性的拦截

时间:2015-07-21 13:44:47

标签: c# simple-injector castle-dynamicproxy

我在我的项目中使用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()方法获取自定义属性时,我会获得nullattribute == null)。我怎样才能获得自定义属性?

P.S。如果为我的服务注册了一个拦截MyTimerInterceptMyLogIntercept它没有完成),在Intercept()方法中我可以获得自定义属性成功attribute != null),但如果两个拦截器都注册了我有问题(attribute == null)。

P.S。我正在使用Castle.Core 3.3.3

2 个答案:

答案 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;