一个方法的多个方面

本文关键字:方法 方面 一个 | 更新日期: 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()结束,否则抛出异常。