您能否建议针对.NET 4.0 defect的变通办法,该结果导致Common Language Runtime检测到无效程序。启动以下程序时(在Visual Studio 2010中)异常:
注意:在Visual Studion 2012中编译同一程序时,不会重现行为。
namespace Namespace1
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
public class Tst1
{
public Action<DataType> Method1<DataType>(Func<DataType> param1) { return this.Method1<DataType>(param1, 0); }
public Action<DataType> Method1<DataType>(Func<DataType> param1, int param2)
{
return param => System.Windows.Forms.MessageBox.Show(param1().ToString() + " " + param.ToString());
}
}
public class TstBase { }
public class Tst2 : TstBase { }
public static class TstExtensions
{
public static string ExtensionMethod<TstType>(this TstType tst)
where TstType : TstBase
{
return "From extension method";
}
}
public class Application
{
public static void Main()
{
Tst1 tst1 = new Tst1();
Tst2 tst2 = new Tst2();
tst1.Method1<string>(tst2.ExtensionMethod)("From main");
}
}
}
注意:.NET Framework 4.0的程序集System.Windows.Forms.dll需要引用以生成项目。
背景资料
我根据第三方提供的低级测试自动化工具开发了高抽象级别的脚本处理关键字驱动的测试自动化框架(该自动化框架利用用于第三方的第三方工具执行高抽象级别的关键字驱动的脚本访问较低级别的图形用户界面)。需要使用上面列出的构造来实施统一值验证方法。
所列代码的每个元素代表以下内容:
Tst1-用于验证值的类
Method1-多态方法,对从UI(用户界面)中检索到的值进行验证,并可以接受超时,直到UI元素获取所需的值
TstBase-通过第三方低级自动化工具API处理所有UI控件的基类
Tst2-用于处理来自第三方低级自动化工具API的某些类型的控件的类
ExtensionMethod-使用来自第三方低层自动化工具API的任何控件处理程序类的实例从所有类型的控件中检索文本的通用方法
Method1返回委托,该委托作为参数传递给其他方法,该方法从test-script-step参数中检索值并立即使用它。总体如下图所示:
testStepParameters.MakeUseOf("Field1ExpectedValue", validation.Verify<string>(field1.GetValue));
最前面的代码段中的
validation.Verify<string>(field1.GetValue)
而不是tst1.Method1<string>(tst2.ExtensionMethod)
的位置。重要的提醒
我找到了解决该缺陷的方法,但我不喜欢它,因为它在代码中增加了一定程度的笨拙性。我发现的解决方法是将扩展方法的直接用法替换为Lambda表达式-即在以下行时错误不会重现:
tst1.Method1<string>(tst2.ExtensionMethod)("From main");
替换为以下行:
tst1.Method1<string>(() => tst2.ExtensionMethod())("From main");
最终形式如下:
testStepParameters.MakeUseOf("Field1ExpectedValue", validation.Verify<string>(() => field1.GetValue()));
当使用一个复杂的调用而不是
field1
变量来检索控件时(可能是委托返回控件),这种变通方法的使用变得完全不愉快(这对于返回控件的状态特别有用,它可以随着时间检查控件状态而无需担心如何获取控件-并使用自己的GetValue
扩展方法实现)。 最佳答案
您可以通过自己创建委托来解决它,而不是让C#为您完成。像这样:
tst1.Method1<string>(new Func<string>(tst2.ExtensionMethod))("From main");