需求:在使用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. LeetCode——Find Duplicate Subtrees

    Question Given a binary tree, return all duplicate subtrees. For each kind of duplicate subtrees, yo ...

  2. vue削笔机

    // 1.vue 是异步更新dom // 2.vue修改多次状态,vue 只会渲染一次 // 3.vue变化侦查机制,每次状态的变化都会发出一个渲染信号. // 检查队列中是否存在,不存在将渲染操作添 ...

  3. Canvas几种模式的区别

    1.screen space-overlay UI显示在最前方 2.screen space-camera 箭头指的是canvas 这样可以放置东西在UI前方和UI后方 3.world space 做 ...

  4. LInux50个基本命令

    cd:(切换)vim:(创建文件)   vi:编辑文件bc:(计算器)quit:退出计算器mkdir:(创建目录)   mkdir -p:递归建立目录rmdir:(删除目录)arch:(显示处理器X8 ...

  5. program发展史及以后预测

    三个阶段:第一个阶段是1950年代到1960年代,是程序设计阶段,基本是个体手工劳动的生产方式.这个时期,一个程序是为一个特定的目的而编制的,软件的通用性是很有限的,软件往往带有强烈的个人色彩.早期的 ...

  6. c++复习要点

    自增和自减运算符有前缀和后缀两种形式,都会改变对象,所以不能对常量对象操作. 前缀形式返回改变后的对象,返回*this. 后缀形式返回改变之前的值,所以必须创建一个代表这个值的独立对象并返回它,是通过 ...

  7. Mac安装MySQLdb遇到的坑

    最近项目移植, 再进行virtualenv环境安装的时候遇到mysql-python死活安装失败 首先是这个错误: sh: /usr/local/bin/mysql_config: No such f ...

  8. Spring源码解析-IOC容器的实现

    1.IOC容器是什么? IOC(Inversion of Control)控制反转:本来是由应用程序管理的对象之间的依赖关系,现在交给了容器管理,这就叫控制反转,即交给了IOC容器,Spring的IO ...

  9. python:使用itchat实现手机控制电脑

    1.准备材料 首先电脑上需要安装了python,安装了opencv更好(非必需) 如果安装了opencv的话,在opencv的python目录下找到cv2.pyd,将该文件放到python的库搜索路径 ...

  10. hdu 6097 Mindis(数学几何,圆心的反演点)

    Mindis Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...