至少有一种可能的解决方案:它将面向方面的方法与依赖注入相结合。不幸的是,这种方法仅限于特定类型的场景(检查答案的最后一部分)。
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 的类时,每个类实例只会调用一个方法
- 这也是一个类范围内的某种代码气味全局变量,因此只有在确实有帮助时才应谨慎应用此方法