Postsharp跳过以装饰用CompilerGenerated属性标记的方法

时间:2014-04-24 17:37:43

标签: c# mstest specflow postsharp

这就是我想要实现的目标: 目前我正在将2500集成测试从nunit转换为mstest,以便我们可以使用Microsoft Test Manager / Lab运行它们。大多数测试需要在我正在处理的产品的用户界面线程上运行,否则它们将无法成功。

这是我的问题: 我创建了一个postharp方面,它将自动运行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);
    }
}

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

  

[assembly:PostSharpTestAspects.MyAspect(       AttributeTargetTypeAttributes = MulticastAttributes.Public                                     | MulticastAttributes.AnyGeneration,       AttributeTargetElements = MulticastTargets.Method,       AttributeTargetMemberAttributes = MulticastAttributes.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..");
    }
}

删除CompilerGenerated属性时,PostSharp会应用方面。

我的问题是: 这种行为是设计的吗?这是一个错误吗? 有一些解决方法吗?也许我需要在assembly属性中以不同方式应用MulticastAttributes?

1 个答案:

答案 0 :(得分:0)

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

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

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

[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]