通过反编译让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 ...
随机推荐
- vue知识汇总
关于slot solt插槽,用来进行预定义,比如app里面的heard,各种情况下未必一致,把每种情况都加上solt,对应的情况下覆盖solt就可以了
- Browserify命令行参数
–outfile, -o: browserify日志打印到文件 –require, -r: 绑定模块名或文件,用逗号分隔 –entry, -e: 应用程序的入口 –ignore, -i: 省略输出 – ...
- UVa 10883 超级平均数(二项式系数+对数计算)
https://vjudge.net/problem/UVA-10883 题意: 给出n个数,每相邻两个数求平均数,依次类推,最后得到1个数,求该数. 思路: 演算一下可以发现最后各个数的系数就是二项 ...
- NPM Scripts -- onchange parallelshell
Watch for changes to the styles.scss file and automatically compile it to the css file. Run multiple ...
- web.config文件配置解决网站上传大文件限制
Asp.Net网站对上传文件的大小,请求执行的时间都做了限制,上传的文件如果超过限制或者执行上传时间超出, 文件上传都将失败. 因此,需要配置web.config来增加最大文件上传的大小和执行超时时间 ...
- ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/usr/local/mysql/tmp/mysql.sock'
查看是否开启服务 # ps -ef | grep mysql root 5605 5457 0 11:45 pts/2 00:00:00 grep mysql 查看my.cnf # cat /etc/ ...
- 安装webpack命令环境
1.通过cnpm安装webpack命令环境,如图 2.安装完后查看webpack的版本,如图
- 利用python3.x实现小爬虫下载贴吧内图片
Hi, I'm back. 寒假在家只有一台笔记本,也懒得把台式机上的键盘拆下来用,因此编程被我暂时搁置,转而在网易云课堂上学了一下Python.可惜的是云课堂的Python教程是基于Python ...
- Request库使用response.text返回乱码问题
我们日常使用Request库获取response.text,这种调用方式返回的text通常会有乱码显示: import requests res = requests.get("https: ...
- 手动建立Mysql表实体类技巧
首先执行一条sql语句,也可以在开发中插入数据.修改数据或者查询数据的某个属性时使用. select sc.COLUMN_NAME from information_schema.COLUMNS as ...