通过反编译让SpecFlow支持多层属性值的验证
需求:在使用SpecFlow时,我希望能对目标对象所关联的对象属性进行验证,但SpecFlow(Version 1.9.0)无法实现。如图中红框,可以对专户所属的金融机构的名称进行验证。

反编译步骤
- 利用ildasm(.net自带)反编译 TechTalk.SpecFlow.dll 生成IL中间代码 一般会生成 *.il 和*.res 一些其它资源文件 *.resources;
- 然后用记事本修改IL文件;
- 然后用ilasm编译中间代码,生成新的 TechTalk.SpecFlow.dll 文件;
- 删除签名。
详细步骤见参考文献[1]
修改前后代码对比
第一处修改
TechTalk.SpecFlow.Assist.TEHelpers 类的 IsPropertyMatchingToColumnName 方法,带“.”的列名不验证是否存在对应的属性。
// 修改前的源代码
1 internal static bool IsPropertyMatchingToColumnName(PropertyInfo property, string columnName)
{
return property.Name.MatchesThisColumnName(columnName);
}
// 修改前的中间语言
1 .method assembly hidebysig static bool IsPropertyMatchingToColumnName(class [mscorlib]System.Reflection.PropertyInfo 'property',
string columnName) cil managed
{
// Code size 13 (0xd)
.maxstack
IL_0000: ldarg.
IL_0001: callvirt instance string [mscorlib]System.Reflection.MemberInfo::get_Name()
IL_0006: ldarg.
IL_0007: call bool TechTalk.SpecFlow.Assist.TEHelpers::MatchesThisColumnName(string,
string)
IL_000c: ret
} // end of method TEHelpers::IsPropertyMatchingToColumnName
// 修改后的源代码
1 internal static bool IsPropertyMatchingToColumnName(PropertyInfo property, string columnName)
{
return ((columnName.IndexOf('.') > -) || property.Name.MatchesThisColumnName(columnName));
}
// 修改后的中间语言
1 .method assembly hidebysig static bool IsPropertyMatchingToColumnName(class [mscorlib]System.Reflection.PropertyInfo 'property',
string columnName) cil managed
{
// Code size 40 (0x28)
.maxstack
.locals init (bool V_0,
bool V_1)
IL_0000: nop
IL_0001: ldarg.
IL_0002: ldc.i4.s
IL_0004: callvirt instance int32 [mscorlib]System.String::IndexOf(char)
IL_0009: ldc.i4.m1
IL_000a: cgt
IL_000c: ldc.i4.
IL_000d: ceq
IL_000f: stloc.
IL_0010: ldloc.
IL_0011: brtrue.s IL_0017
IL_0013: ldc.i4.
IL_0014: stloc.
IL_0015: br.s IL_0026
IL_0017: ldarg.
IL_0018: callvirt instance string [mscorlib]System.Reflection.MemberInfo::get_Name()
IL_001d: ldarg.
IL_001e: call bool TechTalk.SpecFlow.Assist.TEHelpers::MatchesThisColumnName(string,
string)
IL_0023: stloc.
IL_0024: br.s IL_0026
IL_0026: ldloc.
IL_0027: ret
} // end of method TEHelpers::IsPropertyMatchingToColumnName
第二处修改
TechTalk.SpecFlow.Assist.PropertyExtensionMethods 类的 GetPropertyValue 方法,将属性名根据“.”分割后,循环获取关联对线的属性值。
// 修改前的源代码
1 public static object GetPropertyValue(this object @object, string propertyName)
{
return GetThePropertyOnThisObject(@object, propertyName).GetValue(@object, null);
}
// 修改前的中间语言
1 .method public hidebysig static object GetPropertyValue(object 'object',
string propertyName) cil managed
{
.custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( )
// Code size 17 (0x11)
.maxstack
.locals init (class [mscorlib]System.Reflection.PropertyInfo V_0)
IL_0000: ldarg.
IL_0001: ldarg.
IL_0002: call class [mscorlib]System.Reflection.PropertyInfo TechTalk.SpecFlow.Assist.PropertyExtensionMethods::GetThePropertyOnThisObject(object,
string)
IL_0007: stloc.
IL_0008: ldloc.
IL_0009: ldarg.
IL_000a: ldnull
IL_000b: callvirt instance object [mscorlib]System.Reflection.PropertyInfo::GetValue(object,
object[])
IL_0010: ret
} // end of method PropertyExtensionMethods::GetPropertyValue
// 修改后的源代码
1 public static object GetPropertyValue(this object @object, string propertyName)
{
foreach (string str in propertyName.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries))
{
@object = GetThePropertyOnThisObject(@object, str).GetValue(@object, null);
}
return @object;
}
// 修改后的中间语言
1 .method public hidebysig static object GetPropertyValue(object 'object',
string propertyName) cil managed
{
.custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( )
// Code size 64 (0x40)
.maxstack
.locals init (string[] V_0,
string V_1,
char[] V_2,
string[] V_3,
int32 V_4)
IL_0000: ldarg.
IL_0001: ldc.i4.
IL_0002: newarr [mscorlib_6]System.Char
IL_0007: stloc.
IL_0008: ldloc.
IL_0009: ldc.i4.
IL_000a: ldc.i4.s
IL_000c: stelem.i2
IL_000d: ldloc.
IL_000e: ldc.i4.
IL_000f: callvirt instance string[] [mscorlib_6]System.String::Split(char[],
valuetype [mscorlib_6]System.StringSplitOptions)
IL_0014: stloc.
IL_0015: ldloc.
IL_0016: stloc.
IL_0017: ldc.i4.
IL_0018: stloc.s V_4
IL_001a: br.s IL_0037
IL_001c: ldloc.
IL_001d: ldloc.s V_4
IL_001f: ldelem.ref
IL_0020: stloc.
IL_0021: ldarg.
IL_0022: ldloc.
IL_0023: call class [mscorlib]System.Reflection.PropertyInfo TechTalk.SpecFlow.Assist.PropertyExtensionMethods::GetThePropertyOnThisObject(object,
string)
IL_0028: ldarg.
IL_0029: ldnull
IL_002a: callvirt instance object [mscorlib_6]System.Reflection.PropertyInfo::GetValue(object,
object[])
IL_002f: starg.s 'object'
IL_0031: ldloc.s V_4
IL_0033: ldc.i4.
IL_0034: add
IL_0035: stloc.s V_4
IL_0037: ldloc.s V_4
IL_0039: ldloc.
IL_003a: ldlen
IL_003b: conv.i4
IL_003c: blt.s IL_001c
IL_003e: ldarg.
IL_003f: ret
} // end of method PropertyExtensionMethods::GetPropertyValue
参考文献
[1] 编辑IL文件,修改DLL文件
[2] IL指令详细
通过反编译让SpecFlow支持多层属性值的验证的更多相关文章
- Telerik JustDecompile 2014.1.255.0 开发版(.NET反编译神器,免费下载)
Telerik JustDecompile是Telerik公司推出一个免费的.NET反编译工具,支持插件与Visual Studio 2015~2013集成,还能够创建Visual Studio Pr ...
- java反编译工具JD-GUI
这款java反编译工具是由C++写的,是一款免费的非商业用途的软件,(Xjad也不错,但是不支持jar反编译) 一.支持众多.class反编译工具 二.支持反编译jar
- Java 反编译工具几枚(class转java)
1.Java Decompiler Yet another fast Java decompiler. 下载地址:http://jd.benow.ca/#jd-gui-download 一款非常简洁的 ...
- 9款.net反编译的必备神器
编辑来给大家盘点下.net的反编译工具: 1.Reflector Reflector是最为流行的.Net反编译工具.Reflector是由微软员工Lutz Roeder编写的免费程序.Reflecto ...
- .NET反编译工具:de4dot
de4dot是一款C#编写的基于GPLv3协议的一个开源的.net反混淆脱壳工具,是目前.net下非常不错的一款反编译工具. 支持如下混淆器: Agile.NET (aka CliSecure) Ba ...
- 8款非常不错的.Net反编译利器
本人搜集了下8款非常不错的.Net反编译利器: 1.Reflector Reflector是最为流行的.Net反编译工具.Reflector是由微软员工Lutz Roeder编写的免费程序.Refle ...
- .net反编译的九款神器(转载)
.net反编译的九款神器 转载来源: https://www.cnblogs.com/zsuxiong/p/5117465.html 本人搜集了下8款非常不错的.Net反编译利器: 1.Reflec ...
- .net反编译的九款神器
本人搜集了下8款非常不错的.Net反编译利器: 1.Reflector Reflector是最为流行的.Net反编译工具.Reflector是由微软员工Lutz Roeder编写的免费程序.Refle ...
- (转).net反编译工具JustDecompile
开源的反编译工具 JustDecompile https://www.telerik.com/blogs/justdecompile-engine-becomes-open-source https ...
随机推荐
- Ubuntu16.04 anaconda3 opencv已经安装,但是无法import的问题
解决anaconda中已经安装了opencv3,但无法import的问题 你可能遇见的问题: ImportError: No module named cv2 ImportError: libz-a1 ...
- python 类和对象的属性
python类和对象的属性分为类属性和对象属性两大类,类属性属于类,而对象属性属于对象. 1. 父类的对象属性会被子类的对象继承. 2. 父类的类属性会被子类继承,还是作为类属性,如果父类改变了类属性 ...
- Pandas 的使用
1. 访问df结构中某条记录使用loc或者iloc属性.loc是按照index或者columns的具体值,iloc是按照其序值.访问类似于ndarray的访问,用序列分别表示一维和二维的位置. 例如: ...
- C#之多线程
多线程在C#中使用得非常频繁,线程之间的充分利用显得尤为重要,一般的写法都是得不到充分利用资源,本人针对多线程写了一种方法,可以充分利用资源,保证每次同时启动10条线程,现在执行完马上再启动一条,总之 ...
- Vue 备
<div id="app"> <span :class='{red:addClass}'>jam</span> </div> < ...
- 使用 Vs 2015 快速上手 Angular2
Visual Studio 2015 快速上手(使用Angular2)https://angular.cn/guide/visual-studio-2015 使用 Vs 2015 快速上手 Angul ...
- linux exec和xargs的区别
-exec 1.参数是一个一个传递的,传递一个参数执行一次,效率低 2.文件名有空格等特殊字符也能处理 -xargs 1.一次将参数传给命令,可以使用-n控制参数个数 ...
- C++(三十三) — 全局函数、成员函数的区别
区别: (1)全局函数的参数个数,比局部函数要多一个: (2)二者都可,返回元素.返回引用. class test { public: test(int a, int b) { this->a ...
- find命令中选项-path和-prune的使用
在Windows中可以在某些路径中查找文件,也可以设定不在某些路径中查找文件,下面用Linux中的find的命令结合其-path -prune参数来看看在Linux中怎么实现此功能.假如在当前目录下查 ...
- win32调用系统颜色对话框
参考网站:http://blog.csdn.net/u013242177/article/details/50437358 首先要包含commdlg.h头文件,这个是通用对话框的头文件,包括文件对话框 ...