代码之家  ›  专栏  ›  技术社区  ›  Batavia

接口实现上的Postsharp OnMethodBoundryAspect

  •  1
  • Batavia  · 技术社区  · 10 年前

    我的代码大致如下

    IInterface {
    
       public MyClass GetSomething();
    }
    
    public MyService : IInterface {
    
       [NeverNull]
       public GetSomething() {
           if (canAccess) {
              return new MyClass();
           }
           return null;
       }
    }
    
    [Serializable]
    public NeverNullAttribute : OnMethodBoundryAspect {
         OnSuccess(MethodExecutionArgs args ) {
             if (args.ReturnValue == null){
                 args.ReturnValue = new MyClass();
             }
         }
    }
    

    现在,如果我这样调用代码,我的属性似乎会被使用

    public void SomeMethod() {
         var myService = new MyService();
         Assert.IsNotNull(myService.GetSomething()); //this always works
    
    
         var interface = //use unity to get a instance instance of MyService
         Assert.IsNotNull(interface.GetSomething()); //this can fail since GetSomething is properly executed, but the NeverNull aspect doesn't seem to be executed.
    }
    

    我的实际代码有点复杂,但我希望这说明了问题,即如果我使用调用方法的接口方式,OnSuccess不会被执行。

    我用后竖琴表达。如果我确信它能解决这个问题,那么升级将是一个选择。

    更新:我按照建议将方法虚拟化,这似乎没有效果。在其他地方,我直接创建了一个带有属性的类的实例,它确实有效,所以我知道postsharp的一些功能正在发挥作用。

    更新:可能是方面(在另一个项目中定义的)没有正确地编织在我的代码中吗?

    1 回复  |  直到 10 年前
        1
  •  3
  •   Batavia    10 年前

    问题是PostSharp包含在内,但由于某些原因,它没有在包含MyService的项目上启用。 对于任何其他有问题的人,由于IL编织(postsharp的糟糕),如果您使用IL SPY查看方法,OnEntry/OnSuccess方面将在方法内部。例如,方法应该如下所示

    public SomeObject GetSomething(){
        MethodExecutionArgs methodExecutionArgs = new MethodExecutionArgs(null, null);
    
        /* original method code here */ 
    
        methodExecutionArgs.ReturnValue = returnValue;
        <>z__a_1.a0.OnSuccess(methodExecutionArgs);
        return (SomeObject)methodExecutionArgs.ReturnValue;
    }
    

    然而,我注意到这个特定的方法(在这个项目中)没有postsharp代码,而是在我使用postsharp方面的其他地方。

    由于某种原因,甚至我的项目财产上的启用postsharp按钮也不起作用,所以我不得不手动编辑csproj文件。

    如果能在编译时检测到postsharp没有正确加载,那就太好了。