这就是我想要实现的目标: 目前我正在将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?
答案 0 :(得分:0)
PostSharp会忽略在执行方面属性的多播时应用了[CompilerGenerated]
属性的所有类型。此功能是设计使用,需要避免在C#编译器生成的所有类型上应用方面。
生成的类型表示C#编译器的实现细节,默认情况下应用这些属性会将这些实现细节暴露给用户。
但是,PostSharp以非生成类型处理生成的方法,限制较少。这些是用户通常期望默认应用方面的方法。
例如,自动属性访问器标记为[CompilerGenerated]
。您可以通过在方面的AttributeTargetTypeAttributes属性上设置标记MulticastAttributes.CompilerGenerated
和MulticastAttributes.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]