通过反编译让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 ...
随机推荐
- java中使用Ehcache缓存数据
知识点:在java项目中,使用ehcache缓存数据 参考博客:http://www.cnblogs.com/jingmoxukong/p/5975994.html ()概述 Ehcache是一个纯J ...
- Flink快速入门
文章目录 1 安装:下载并启动 1.1 下载 1.2 启动一个local模式的Flink集群 2 运行例子 3 集群模式安装 4 Flink on YARN 安装:下载并启动 Flink可以在Linu ...
- 【Network Architecture】SegNet论文解析(转)
文章来源: https://blog.csdn.net/fate_fjh/article/details/53467948 Introduction 自己制作国内高速公路label,使用SegNet训 ...
- 06_zookeeper_原生API使用2
1. 设置znode节点数据(同步) import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java ...
- hiho 1323 : 回文字符串 dp
#1323 : 回文字符串 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个字符串 S ,最少需要几次增删改操作可以把 S 变成一个回文字符串? 一次操作可以在任 ...
- Asp.Net将Session保存在数据库中
1.由于项目dll文件变动比较频繁,而保存登陆的状态又保存在Session中,所以导致用户经常无故掉线.(dll变动的时候导致Session丢失) 2.有一种方法可以长期保存session,那就是se ...
- 13.LockSupport工具
1. LockSupport简介 在之前介绍AQS的底层实现,已经在介绍java中的Lock时,比如ReentrantLock,ReentReadWriteLocks,已经在介绍线程间等待/通知机制使 ...
- 转:25个Java机器学习工具和库
转自:http://www.cnblogs.com/data2value/p/5419864.html 本列表总结了25个Java机器学习工具&库: 1. Weka集成了数据挖掘工作的机器学习 ...
- 二十五 Python分布式爬虫打造搜索引擎Scrapy精讲—Requests请求和Response响应介绍
Requests请求 Requests请求就是我们在爬虫文件写的Requests()方法,也就是提交一个请求地址,Requests请求是我们自定义的 Requests()方法提交一个请求 参数: ur ...
- confluence wiki 破解安装操作流程
准备postgres数据库安装 步骤1:命令: docker pull postgres 步骤2:安装: docker run --name postgresdb -p 5432:5432 -e PO ...