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

反编译步骤

  1. 利用ildasm(.net自带)反编译 TechTalk.SpecFlow.dll 生成IL中间代码 一般会生成 *.il 和*.res 一些其它资源文件 *.resources;
  2. 然后用记事本修改IL文件;
  3. 然后用ilasm编译中间代码,生成新的 TechTalk.SpecFlow.dll 文件;
  4. 删除签名。

  详细步骤见参考文献[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支持多层属性值的验证的更多相关文章

  1. Telerik JustDecompile 2014.1.255.0 开发版(.NET反编译神器,免费下载)

    Telerik JustDecompile是Telerik公司推出一个免费的.NET反编译工具,支持插件与Visual Studio 2015~2013集成,还能够创建Visual Studio Pr ...

  2. java反编译工具JD-GUI

    这款java反编译工具是由C++写的,是一款免费的非商业用途的软件,(Xjad也不错,但是不支持jar反编译) 一.支持众多.class反编译工具 二.支持反编译jar

  3. Java 反编译工具几枚(class转java)

    1.Java Decompiler Yet another fast Java decompiler. 下载地址:http://jd.benow.ca/#jd-gui-download 一款非常简洁的 ...

  4. 9款.net反编译的必备神器

    编辑来给大家盘点下.net的反编译工具: 1.Reflector Reflector是最为流行的.Net反编译工具.Reflector是由微软员工Lutz Roeder编写的免费程序.Reflecto ...

  5. .NET反编译工具:de4dot

    de4dot是一款C#编写的基于GPLv3协议的一个开源的.net反混淆脱壳工具,是目前.net下非常不错的一款反编译工具. 支持如下混淆器: Agile.NET (aka CliSecure) Ba ...

  6. 8款非常不错的.Net反编译利器

    本人搜集了下8款非常不错的.Net反编译利器: 1.Reflector Reflector是最为流行的.Net反编译工具.Reflector是由微软员工Lutz Roeder编写的免费程序.Refle ...

  7. .net反编译的九款神器(转载)

    .net反编译的九款神器  转载来源: https://www.cnblogs.com/zsuxiong/p/5117465.html 本人搜集了下8款非常不错的.Net反编译利器: 1.Reflec ...

  8. .net反编译的九款神器

    本人搜集了下8款非常不错的.Net反编译利器: 1.Reflector Reflector是最为流行的.Net反编译工具.Reflector是由微软员工Lutz Roeder编写的免费程序.Refle ...

  9. (转).net反编译工具JustDecompile

    开源的反编译工具  JustDecompile https://www.telerik.com/blogs/justdecompile-engine-becomes-open-source https ...

随机推荐

  1. storm(二) 事务机制

    前言 为了保证tuple的强有序和exactly-once语义,storm提供了事务机制,为每个tuple提供一个id 设计方法1 为每个tuple设置一个事务id,在数据库保存事务id和当前处理的i ...

  2. L1-3 宇宙无敌加法器 - 令人激动的一道题目

    L1-3 宇宙无敌加法器 - 令人激动的一道题目 感觉好久没有这么认真的做一道题了,今天看到一句话, 说是编程是一个工程型的工作,想要学好,"无他,唯手熟尔" 之前觉得自己笨,怀疑 ...

  3. codeforce AIM tech Round 4 div 2 B rectangles

    2017-08-25 15:32:14 writer:pprp 题目: B. Rectangles time limit per test 1 second memory limit per test ...

  4. 在HTTP通讯过程中,是客户端还是服务端主动断开连接?

    比如说:IE访问IIS,获取文件,肯定是要建立一个连接,这个连接在完成通讯后,是客户端Close了连接,还是服务端Close了连接.我用程序测模拟IE和IIS,都没有收到断开连接的消息,也就是都没有触 ...

  5. (局部刷新)jquery.ajax提交并实现单个div刷新

    web开发中我们经常会遇到局部刷新页面的需求,以前我经常使用ajax和iframe实现局部刷新,后来做政府的项目,对页面的样式要求比较多,发现使用iframe控制样式什么的很麻烦,所以就采用了新的办法 ...

  6. 使用 Vs 2015 快速上手 Angular2

    Visual Studio 2015 快速上手(使用Angular2)https://angular.cn/guide/visual-studio-2015 使用 Vs 2015 快速上手 Angul ...

  7. 010PHP基础知识——运算符(三)

    <?php /** * 位运算符: * 1:&按位与:左右两边的数,同位都为1,返回是1,否则返回是0 */ /*$a = 5; $b = 6; $a = decbin($a);//10 ...

  8. System.Zip

    自XE2增加的System.Zip单元很好.注意事项: 1.文件压缩到文档后所使用的文件名会成为解压后的文件名,如果该文件名为指定文件名且无后缀名,那么解压出来的文件名也没有后缀名:

  9. 【前端工具】 在 Windows 下安装 GruntJS——教程(译)

    在你安装 Grunt.js 之前你需要先安装 Node.js.对于本教程而言,我已经安装好了 node.js v0.10.0. 我将要安装 Grunt.js v0.4.1.警告:如果你已经安装了 Gr ...

  10. SpringInAction--自动化装配Bean(隐式装配)

    关于Bean的介绍就具体不多介绍了,,, Spring在配置时候有三种方案可选 1.在xml中进行显示配置 2.在java中进行显示配置 3.隐式的Bean发现机制和自动装配 今天学习的就是自动化装配 ...