PostSharp,除了使用方法接口之外如何注入一个值?

时间:2013-01-05 20:27:08

标签: postsharp aop

除了修改/覆盖接口中的一个参数之外,还有将值注入方法吗?例如:

[Serializable]
public class MyTestAttribute : MethodInterceptionAspect
{
     public override void OnInvoke(MethodInterceptionArgs args)
     {
         String someValue = "123";
     }
}

public class MyClass
{
     [MyTest]
     public void doSomething()
     {
        String otherValue = "456" + someValue;
     }

}

在方面声明someValue,但在doSomething方法中可以访问,而不通过方法接口传入它。这可能吗?

1 个答案:

答案 0 :(得分:3)

至少有一种可能的解决方案:将面向方面的方法依赖注入结合起来。 不幸的是,这种方法仅限于特定类型的场景(查看答案的最后一部分)。

InjectedAspect建议

首先,将someValue定义为包含目标方法的类的可选依赖项。您可以通过使用此依赖

提取类外的接口来完成此操作
public interface IServiceWithDependency
{
    int SomeValue { get; set; }
}

其次,制作目标类来实现这个接口

public class MyClass : IServiceWithDependency
{
    // dependency
    public int SomeValue { get; set; } 

    // aspect
    [InjectedAspect] 
    public void DoSomething()
    {
        string otherValue = "456" + SomeValue;
    }
}

现在我们需要方面来注入这种依赖

[Serializable]
public class InjectedAspectAttribute : MethodInterceptionAspect
{
    public override void OnInvoke(MethodInterceptionArgs args)
    {
        if (args.Instance is IServiceWithDependency)
        {
            // inject actual value of dependency
            (args.Instance as IServiceWithDependency).SomeValue = 123;
        }

        args.Proceed();
    }
}

您可以选择添加编译时验证,以确保此方面仅应用于实现IServiceWithDependency的类

  [Serializable]
        public class InjectedAspectAttribute : MethodInterceptionAspect
        {
            public override bool CompileTimeValidate(MethodBase method)
            {
                var result = true;
                var methodInfo = method as MethodInfo;

                if (!typeof(IServiceWithDependency).IsAssignableFrom(method.DeclaringType))
            {
                Message.Write(methodInfo, SeverityType.Error, "999", string.Format("Only class derived from IServiceWithDependencyallowed, {0} not implements IServiceWithDependency", method.DeclaringType));

                result = false;
            }

            return result;
        }

        public override void OnInvoke(MethodInterceptionArgs args)
        {
            /* … */
        }
    }

提供完整样本here

何时申请以及此方面的方式

最初的想法来自事务管理方面,当没有环境TransactionScope时,而是将事务对象注入到需要处理事务的每个类中。一些重要的细节:

  • 这方面不仅不是线程安全的,而且如果你在一个类实例上调用这个方面装饰的几个方法,你可能会覆盖以前注入的值
  • 当你在MVC应用程序中有类似Controller的类时,以前的限制不是问题,并且每个类的实例只调用一个方法
  • 这也是某类代码在某一类范围内的全局变量,所以这种方法只有在真正有用的情况下才应该谨慎应用