反射以查找应用了 PostSharp 方面的所有方法

Reflection to find all methods with a PostSharp aspect applied

我创建了一个 OnMethodBoundary 方面来跟踪模板方法中的进度事件。就整体进度而言,了解其中一项有用的事情是我的流程在完成之前所需的进度步骤数,即用我的 [AffectsProgress] 属性标记的方法数。

我尝试使用 System.Reflection 来确定它,而不是对其进行硬编码并在添加和删除方法时必须对其进行维护(我尝试了很多变体):

typeof (MyModuleWithProgressSteps)
.GetMethods(/* whatever BindingFlags I need */)
.SelectMany(x => x.CustomAttributes.Where(attribute => attribute.AttributeType == typeof (AffectsProgress)))

然而,即使我在删除 Where 子句时能够看到其他属性,我也无法找到任何 PostSharp 方面。我天真的猜测是,在执行时干扰调用堆栈的 PostSharp 方面实际上并不是传统的方法属性,因此 System.Reflection 库看不到它们。

有谁知道我可以通过 System.Reflection 或 PostSharp 本身获得我正在寻找的东西的方法吗?我发现 ReflectionSearch and IAspectRepositoryService 需要终极版,但我不确定这些是否足够。

编辑:由@Daniel Balas 解决。使用该答案和我找到的信息 here 我最终得到了一个看起来像这样的自定义方面,并且能够在运行时通过反射检测到:

    [Serializable]
    [MulticastAttributeUsage(PersistMetaData = true)]
    internal class AffectsProgress : OnMethodBoundaryAspect
    {
        public override void OnExit(MethodExecutionArgs args)
        {
            // do all my progress-related stuff here
        }
    }

方面由 PostSharp 编织为 IL 代码,因此表示方面的属性在 PostSharp 完成其 post 处理后消失。

ReflectionSearch 应该在这里有所帮助(我从来没有自己尝试过),因为它说:

These methods are only available at build time.

在构建时,这是在属性消失之前访问属性的最后机会。

在多播阶段默认删除多播属性,并且所有实例(如果您将多播到所有方法,则可能有很多)在内部传递给 Aspect Framework。

您可以告诉多播引擎不要删除元数据,以便您可以在运行时访问该属性。这是这样做的:

[MulticastAttributeUsage(PersistMetaData = true)]

然后,方面属性将出现在应用它们的声明中(即方法上的 MethodLevelAspect,类型上的 TypeLevel 方面等)。