使用Mono.Cecil调用Convert.ToSingle(字符串参数)

时间:2013-09-10 13:16:35

标签: .net mono.cecil valueconverter

正如标题所说,我想用Mono.Cecil打电话给那个方法,但我不知道怎么做。

1 个答案:

答案 0 :(得分:1)

如何使用Mono.Cecil注入方法调用:

  1. 阅读目标集会。
  2. 找到注入方法调用所需的点。要求的是 指向注入所有参数的方法体的指令 堆栈上的方法。
  3. 查找注入的方法。
  4. 生成调用此方法的指令。
  5. 在所需点之后插入生成的指令(来自声明 2)。
  6. 重写目标程序集。
  7. 注入Convert.ToSingle(字符串)调用的代码示例:

    目标方法

    namespace YourTargetNamespace
    {
        public class YourTargetClass
        {
            public Single YourTargetMethod()
            {
                var str = "1";
                return 0; //Convert.ToSingle(str);
            }
        }
    }
    

    在不同的程序集中注入代码和测试

        [Test]
        public void InjectConverToSingleTest()
        {
            InjectConverToSingle();
    
            var engine = new YourTargetClass();
            Assert.That(engine.YourTargetMethod(), Is.EqualTo(1.0f));
        }
    
        public void InjectConverToSingle()
        {
            const string assemblyName = "YourTargetAssembly.dll";
            var assemble = AssemblyDefinition.ReadAssembly(assemblyName);
            var type = assemble.MainModule.GetType("YourTargetNamespace.YourTargetClass");
            var method = type.Methods.First(m => m.Name == "YourTargetMethod");
            var il = method.Body.GetILProcessor();
            var requiredPoint = method.Body.Instructions
                .First(instruction => instruction.OpCode.Code == Code.Ldstr &&
                                      (string)instruction.Operand == "1");
    
            var convertInstruction = CreateConvertInstruction(assemble.MainModule);
            il.InsertAfter(requiredPoint, convertInstruction);
            il.InsertAfter(convertInstruction, Instruction.Create(OpCodes.Ret));
            assemble.Write(assemblyName);
        }
    
        public Instruction CreateConvertInstruction(ModuleDefinition module)
        {
            var typeConvert = module.Import(typeof(Convert));
            var methodToSingle = typeConvert.Resolve()
                .Methods.First(method => method.Name == "ToSingle" &&
                                         method.Parameters.Count == 1 &&
                                         method.Parameters[0].ParameterType.FullName == module.TypeSystem.String.FullName);
            var importedMethodToSingle = module.Import(methodToSingle);
    
            return Instruction.Create(OpCodes.Call, importedMethodToSingle);
        }