如何确定编织方法?

时间:2016-04-25 10:23:18

标签: postsharp

我将PostSharp方面(以下实现为AutoData)应用于测试方法:

[Theory, AutoData( additionalTypes: typeof(MethodFormatter) )] public void MethodFormatsAsExpected( FormatterFactory sut ) { var name = MethodBase .GetCurrentMethod() .Name; // Resolves to "<MethodFormatsAsExpected>z__OriginalMethod" }

如您所见,MethodBase.GetCurrentMethod的结果是返回编织的身体。我想要检索方面编织的(父)目标方法,基本上相当于:

var method = GetType() .GetMethod( nameof(MethodFormatsAsExpected) ) .Name; // Returns "MethodFormatsAsExpected"

但是以MethodBase.GetCurrentMethod提供的通用静态方式。

这可能吗?

1 个答案:

答案 0 :(得分:1)

就其本身而言,无法在运行时从代码中获取原始方法。

但是,您可以使用方面来增强需要此信息的方法,并记住您在(线程)静态堆栈变量中的方法。

从概念上讲,以下代码使用AssemblyLevelAspect来增强您使用内部CurrentMethodService.Get()调用MethodLevelAspect的所有方法,该方法在执行方法时将当前方法推送到堆栈中并弹出当方法退出时。

public static class CurrentMethodServices
{
    [ThreadStatic]
    private static Stack<MethodBase> slots;

    internal static Stack<MethodBase> Slots
    {
        get { return slots ?? (slots = new Stack<MethodBase>()); }
    }

    public static MethodBase Get()
    {
        return Slots.Peek();
    }

    internal static void Enter(MethodBase slot)
    {
        Slots.Push(slot);
    }

    internal static void Exit()
    {
        Slots.Pop();
    }
}

[PSerializable]
[MulticastAttributeUsage(MulticastTargets.Assembly, Inheritance = MulticastInheritance.Multicast)]
public class CurrentMethodPolicy : AssemblyLevelAspect, IAspectProvider
{
    public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
    {
        foreach (
            MethodUsageCodeReference methodRef in
                ReflectionSearch.GetMethodsUsingDeclaration(typeof(CurrentMethodServices).GetMethod("Get",
                    BindingFlags.Public | BindingFlags.Static)))
        {
            if ((methodRef.Instructions & MethodUsageInstructions.Call | MethodUsageInstructions.CallVirtual) != 0)
                yield return new AspectInstance(methodRef.UsingMethod, new MethodEnhancement());
        }
    }

    [PSerializable]
    public class MethodEnhancement : IMethodLevelAspect
    {
        [PNonSerialized]
        private MethodBase method;

        public void RuntimeInitialize(MethodBase method)
        {
            this.method = method;
        }

        [OnMethodEntryAdvice]
        [SelfPointcut]
        public void OnMethodEntry(MethodExecutionArgs args)
        {
            CurrentMethodServices.Enter(this.method);
        }

        [OnMethodExitAdvice]
        [SelfPointcut]
        public void OnMethodExit(MethodExecutionArgs args)
        {
            CurrentMethodServices.Exit();
        }
    }
}

要使用该方面,只需将其应用于装配体即可。

[assembly: CurrentMethodPolicy]

这种方法的一个很好的副作用是方法查找非常快。

请注意,您不应仅使用增强型代码中的任何其他方面方法使用CurrentMethodServices.Get()

此外,将方面继承设置为Multicast会强制PostSharp将方面应用于引用程序集,因此您只需将其应用于声明方面的程序集中。

最后,CurrentMethodServices.Get()在未使用PostSharp的项目中使用时无效。