一个方法的多个方面
本文关键字:方法 方面 一个 | 更新日期: 2023-09-27 18:06:21
在我的应用程序中,我以前使用常规的c#属性来"注释"一个方法。例如:
<>之前
[Foo(SomeKey="A", SomeValue="3")]
[Foo(SomeKey="B", SomeValue="4")]
public void TheMethod()
{
SpecialAttributeLogicHere();
}
之前SpecialAttributeLogicHere()所做的是反思性地查看注释这个特定方法的所有foo属性。然后,它会(自己)为所有键和值创建自己的字典。
我现在正试图移动到PostSharp,因为SpecialAttributeLogic可以放在一个方面(并从方法体中删除,这更干净!),在OnEntry。Foo将被一个扩展了OnMethodBoundaryAspect的方面所取代。
我仍然喜欢这样使用它:
[Foo(SomeKey="A", SomeValue="3")]
[Foo(SomeKey="B", SomeValue="4")]
但是如果Foo有一个OnEntry,这意味着"SpecialAttributeLogic"将被执行两次。我基本上需要"收集"每个Foo()中的所有键和值到一个字典中,然后对其应用一些逻辑。
如何使用PostSharp做到这一点(或最佳实践)?谢谢!
看起来您想要在您的方法内部构建一个nameevaluepair。您不能对方面这样做。我的建议是你使用MethodInterceptionAspect并反映方法上的属性,然后构建你的集合并通过参数(可能使用重载方法)将其传递给方法,或者将其设置为类成员。
您可以在编译时反映这些值,以保持最佳性能。
这里有一个快速解决你问题的方法。它有点丑(您需要进行修改以适应)。还有其他方法,但它们不是"通用的"。namespace ConsoleApplication12
{
class Program
{
static void Main(string[] args)
{
MyExampleClass ec = new MyExampleClass();
ec.MyMethod();
}
}
public class MyExampleClass
{
[Special(Key = "test1", Value = "1234")]
[Special(Key = "test2", Value = "4567")]
[MyAspect]
public void MyMethod()
{
MyMethod(new Dictionary<string, string>());
}
public void MyMethod(Dictionary<string, string> values)
{
//Do work
}
}
[Serializable]
public class MyAspect : MethodInterceptionAspect
{
Dictionary<string, string> values = new Dictionary<string, string>();
MethodInfo target;
public override void CompileTimeInitialize(System.Reflection.MethodBase method, AspectInfo aspectInfo)
{
target = method.DeclaringType.GetMethod(method.Name, new Type[] { typeof(Dictionary<string, string>) });
foreach (Attribute a in method.GetCustomAttributes(false))
{
if (a is SpecialAttribute)
{
values.Add(((SpecialAttribute)a).Key, ((SpecialAttribute)a).Value);
}
}
}
public override void OnInvoke(MethodInterceptionArgs args)
{
if (values == null || values.Count < 1)
{
args.Proceed();
}
else
{
target.Invoke(args.Instance, new object[] { values });
}
}
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true) ]
public class SpecialAttribute : Attribute
{
public string Key { get; set; }
public string Value { get; set; }
}
}
目标和值都在编译时(而不是运行时)初始化,以便在运行时使用。它们在编译时被方面序列化。这样可以节省运行时的反射命中。
只是作为一个说明,我最终使用MethodInterceptionAspect和只重写OnInvoke。在OnInvoke中,我查看了args.Method.GetCustomAttributes(),给了我所有的System。我设置的属性(即DustinDavis示例中的SpecialAttribute)。
使用这些属性和它们的属性,我可以运行我需要运行的逻辑。如果逻辑成功,则以args.Proceed()结束,否则抛出异常。