Postsharp跳过对用CompilerGenerated属性标记的方法进行装饰

本文关键字:方法 属性 CompilerGenerated Postsharp | 更新日期: 2023-09-27 17:59:50

这就是我想要实现的目标:目前,我正在将2500个集成测试从nunit转换为mstest,以便我们可以使用Microsoft测试管理器/实验室运行它们。大多数测试都需要在我正在开发的产品的用户界面线程上运行,否则它们将不会成功。

这是我的问题:我创建了一个postsharp方面,它将自动运行mstest测试方法,该方法将初始化测试环境并在UI线程上运行测试。除使用Specflow创建的测试外,此操作效果良好。Specflow生成用System.Runtime.CompilerServices.CompilerGenerated特性标记的代码隐藏类。当一个类被标记为该属性时,Postsharp似乎会跳过其中的所有方法

该方面是在程序集级别上定义的。我曾尝试在注册过程中使用MulticastAttributes.CompilerGenerated属性,但它似乎不会改变行为。当我把方面直接放在一个方法上时,它就起作用了。

我使用的是Postsharp的最新稳定版本(目前为3.1)

示例方面:

[Serializable]
public class MyAspect : PostSharp.Aspects.OnMethodBoundaryAspect
{
    public override void OnEntry(PostSharp.Aspects.MethodExecutionArgs args)
    {
        Console.WriteLine("Starting {0}", args.Method.Name);
    }
    public override void OnExit(PostSharp.Aspects.MethodExecutionArgs args)
    {
        Console.WriteLine("Completed {0}", args.Method.Name);
    }
}

我试图将其应用于的代码:

[程序集:PostSharpTestAspects.MyAspect(AttributeTargetTypeAttributes=多播属性.Public|MulticastAttributes.AnyGeneration,AttributeTargetElements=多播目标.方法,AttributeTargetMemberAttributes=多播属性.Public|MulticastAttributes.AnyGeneration)]

class Program
{
    static void Main(string[] args)
    {
        new MyTestClass().MyTestMethod();
        Console.WriteLine("Press a key to exit..."); 
        Console.ReadKey();
    }
}
[System.Runtime.CompilerServices.CompilerGenerated]
public class MyTestClass
{        
    public void MyTestMethod()
    {
        Console.WriteLine("Executing MyTestMethod..");
    }
}

删除编译器生成的属性时,PostSharp将应用方面。

我的问题是:这种行为是故意的吗?这是个虫子吗?有什么变通办法吗?也许我需要在程序集属性中以不同的方式应用MulticastAttributes?

Postsharp跳过对用CompilerGenerated属性标记的方法进行装饰

PostSharp在执行方面属性的多播时忽略所有应用了[CompilerGenerated]属性的类型。此功能是经过设计的,需要它来避免在C#编译器生成的所有类型上应用方面。生成的类型表示C#编译器的实现细节,默认情况下应用这些属性将向用户公开这些实现细节。

然而,PostSharp在非生成类型中处理生成方法的限制较少。这些是用户通常期望在默认情况下应用方面的方法。例如,自动特性访问器标记为[CompilerGenerated]。可以通过在方面的AttributeTargetTypeAttributes属性上设置标志MulticastAttributes.CompilerGeneratedMulticastAttributes.UserGenerated来控制此行为。

如果需要将方面应用于编译器生成的类型,那么可以通过实现自己的方面提供程序并在程序集级别上应用它来实现。

[MulticastAttributeUsage(MulticastTargets.Assembly)]
public class SampleAspectProvider : MulticastAttribute, IAspectProvider
{
    public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
    {
        var myAspect = new MyAspect();
        var assembly = (Assembly) targetElement;
        foreach (var type in assembly.GetTypes())
        {
            if (/* type is a valid target */)
            {
                foreach (var methodInfo in type.GetMethods())
                {
                    yield return new AspectInstance(methodInfo, myAspect);
                }
            }
        }
    }
}

并应用于目标组件:

[assembly: SampleAspectProvider]