1

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

[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;
     }

}

WheresomeValue在方面中声明,但可以在 doSomething 方法中访问,而无需通过方法接口传递它。这可能吗?

4

1 回答 1

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)
        {
            /* … */
        }
    }

完整样本可在此处获得

什么时候申请,这个方面是什么场景

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

  • 这个方面不仅不是线程安全的,而且如果你在一个类的实例上调用几个用这个方面装饰的方法,你可能会覆盖以前注入的值
  • 以前的限制不是问题,当您在 MVC 应用程序中有类似 Controller 的类时,每个类实例只会调用一个方法
  • 这也是一个类范围内的某种代码气味全局变量,因此只有在确实有帮助时才应谨慎应用此方法
于 2013-01-06T16:33:35.147 回答