标签: ilgenerator

为什么Calli比代表电话更快?

我正在玩Reflection.Emit并找到关于这个很少用的东西EmitCalli.好奇,我想知道它是否与常规方法调用有任何不同,所以我掀起了下面的代码:

using System;
using System.Diagnostics;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Security;

[SuppressUnmanagedCodeSecurity]
static class Program
{
    const long COUNT = 1 << 22;
    static readonly byte[] multiply = IntPtr.Size == sizeof(int) ?
      new byte[] { 0x8B, 0x44, 0x24, 0x04, 0x0F, 0xAF, 0x44, 0x24, 0x08, 0xC3 }
    : new byte[] { 0x0f, 0xaf, 0xca, 0x8b, 0xc1, 0xc3 };

    static void Main()
    {
        var handle = GCHandle.Alloc(multiply, GCHandleType.Pinned);
        try
        {
            //Make the native method executable
            uint old;
            VirtualProtect(handle.AddrOfPinnedObject(),
                (IntPtr)multiply.Length, 0x40, …
Run Code Online (Sandbox Code Playgroud)

.net c# reflection.emit ilgenerator

42
推荐指数
2
解决办法
4255
查看次数

如何使用IL改变盒装结构

想象一下,我们有一个可变的struct(是的,不要开始):

public struct MutableStruct
{
    public int Foo { get; set; }
    public override string ToString()
    {
        return Foo.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

使用反射,我们可以获取一个盒装实例,struct并在框内变异:

// this is basically what we want to emulate
object obj = new MutableStruct { Foo = 123 };
obj.GetType().GetProperty("Foo").SetValue(obj, 456);
System.Console.WriteLine(obj); // "456"
Run Code Online (Sandbox Code Playgroud)

我会喜欢做的是写一些IL可以做同样的,因为这-但速度更快.我是一个元编程迷; p

拆箱 - 任何值并使用常规IL改变值是微不足道的 - 但是你不能只是在之后调用它,因为这将创建一个不同的框.我我们需要做的是将它复制到现有的盒子上.我已经调查了ldobj/ stobj,但那些似乎没有做到这一点(除非我遗漏了什么).

那么:是否存在这样做的机制?或者我必须限制自己反思以执行盒装structs 的就地更新?

换句话说:什么... evil goes here...

var method = …
Run Code Online (Sandbox Code Playgroud)

.net c# metaprogramming ilgenerator

26
推荐指数
2
解决办法
1119
查看次数

用于Windows应用商店应用API的.NET中Emit.OpCodes的用途?

我正在考虑将第三方库移植到.NET for Windows Store应用程序.该库通过调用ILGenerator.Emit方法重载过度使用System.Reflection.Emit.OpCodes.

.NET for Windows Store Apps API中,包含了OpCode结构和OpCodes类,但没有ILGenerator类,并且我已经找不到替换.

我显然失去了一些东西,但:没有ILGenerator一流的,什么是包括的目的System.Reflection.Emit.OpCodeOpCodes.NET的Windows Store应用程序的API?

c# reflection.emit ilgenerator opcodes windows-store-apps

15
推荐指数
1
解决办法
475
查看次数

ILGenerator捕获异常不起作用

我通过使用生成类型的包装器System.Reflection.Emit.有一次,原始对象可能会在access(FaultException)上抛出一个错误,错误应该由我try { } catch (Exception e) { }实现的错误捕获,但事实并非如此.

代码由ILSpy正确显示.

try
{
    if (original.Station != null)
    {
        if (objectDictionary.ContainsKey(original.Station))
        {
            this.Station = (objectDictionary[original.Station] as StationWrapper);
        }
        else
        {
            this.Station = new StationWrapper(original.Station, objectDictionary);
        }
    }
}
catch (Exception arg_6D_0)
{
    ReportManager.Log(arg_6D_0);
}
Run Code Online (Sandbox Code Playgroud)

代码生成

这是组装生成的代码.

Label ex = il.BeginExceptionBlock();
....
// Exception block end
il.Emit(OpCodes.Leave, ex);
il.BeginCatchBlock(typeof(Exception));
il.Emit(OpCodes.Call, ReportManager_Log);
il.EndExceptionBlock();
Run Code Online (Sandbox Code Playgroud)

编辑

例外是被用户代码捕获而不是被IL-Code捕获.

拆卸

在这里删除了客户的一些名称空间.写行已在最后几分钟添加.

.try
{
    IL_0019: ldarg.1
    IL_001a: call instance class [...]...Station [...]...StationBase::get_Station() …
Run Code Online (Sandbox Code Playgroud)

c# exception-handling reflection.emit ilgenerator

12
推荐指数
2
解决办法
1398
查看次数

为什么IL.Emit方法添加额外的nop指令?

我有这样的代码,发出一些IL调用指令string.IndexOf一对null对象:

MethodBuilder methodBuilder = typeBuilder.DefineMethod(
                                             "Foo",
                                             MethodAttributes.Public,
                                             typeof(void), Array.Empty<Type>());
var methodInfo = typeof(string).GetMethod("IndexOf", new[] {typeof(char)});
ILGenerator ilGenerator = methodBuilder.GetILGenerator();

ilGenerator.Emit(OpCodes.Ldnull);
ilGenerator.Emit(OpCodes.Ldc_I4_S, 120);
ilGenerator.Emit(OpCodes.Call, methodInfo);
ilGenerator.Emit(OpCodes.Ret);
Run Code Online (Sandbox Code Playgroud)

这是生成的IL代码:

.method public instance int32  Foo() cil managed
{
  // Code size       12 (0xc)
  .maxstack  2
  IL_0000:  ldnull
  IL_0001:  ldc.i4.s   120
  IL_0003:  nop
  IL_0004:  nop
  IL_0005:  nop
  IL_0006:  call       instance int32 [mscorlib]System.String::IndexOf(char)
  IL_000b:  ret
} // end of method MyDynamicType::Foo
Run Code Online (Sandbox Code Playgroud)

如您所见,nop指令前有三条call指令.

首先我考虑了Debug/Release构建,但这不是编译器生成的代码,我发出了原始的IL代码,并希望看到它原样.

所以我的问题是为什么 …

c# cil reflection.emit ilgenerator

12
推荐指数
2
解决办法
212
查看次数

使用Reflection.Emit发出"using(x){...}"块?

我正在尝试在C#中使用Reflection.Emit来发出一个using (x) { ... }块.

在我处于代码中的时候,我需要获取堆栈的当前顶部,这是一个实现IDisposable的对象,将其存储在局部变量中,在该变量上实现一个使用块,然后在其中添加更多代码(我可以处理最后一部分.)

这是我尝试编译并在Reflector中查看的C#代码示例:

public void Test()
{
    TestDisposable disposable = new TestDisposable();
    using (disposable)
    {
        throw new Exception("Test");
    }
}
Run Code Online (Sandbox Code Playgroud)

这在Reflector中看起来像这样:

.method public hidebysig instance void Test() cil managed
{
    .maxstack 2
    .locals init (
        [0] class LVK.Reflection.Tests.UsingConstructTests/TestDisposable disposable,
        [1] class LVK.Reflection.Tests.UsingConstructTests/TestDisposable CS$3$0000,
        [2] bool CS$4$0001)
    L_0000: nop 
    L_0001: newobj instance void LVK.Reflection.Tests.UsingConstructTests/TestDisposable::.ctor()
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: stloc.1 
    L_0009: nop 
    L_000a: ldstr "Test"
    L_000f: newobj instance void [mscorlib]System.Exception::.ctor(string)
    L_0014: throw 
    L_0015: ldloc.1 
    L_0016: …
Run Code Online (Sandbox Code Playgroud)

c# reflection.emit using-statement ilgenerator

11
推荐指数
1
解决办法
916
查看次数

动态创建基类的类型和调用构造函数

我需要动态创建一个类.大多数工作正常,但我坚持生成构造函数.

AssemblyBuilder _assemblyBuilder =
        AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("MyBuilder"),                                                        AssemblyBuilderAccess.Run);

ModuleBuilder _moduleBuilder = _assemblyBuilder.DefineDynamicModule("MyModule");

public static object GetInstance<TSource, TEventArgs>(this TSource source, string eventName)
    where TSource : class
{
    var typeName = "MyTypeName";
    var typeBuilder = _moduleBuilder.DefineType(typeName, TypeAttributes.Class | TypeAttributes.Public);

    // create type like class MyClass : GenericType<MyClass, TSource, TEventArgs>
    var baseNotGenericType = typeof(GenericType<,,>);
    var baseType = baseNotGenericType.MakeGenericType(typeBuilder, typeof(TSource), typeof(TEventArgs)); 
    typeBuilder.SetParent(baseType);


    // the base class contains one constructor with string as param
    var baseCtor = baseNotGenericType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(string) }, null); …
Run Code Online (Sandbox Code Playgroud)

c# reflection reflection.emit ilgenerator

11
推荐指数
2
解决办法
1万
查看次数

ILGenerator周围有一个很好的包装器吗?

我现在使用System.Reflection.Emit一段时间了,发现它(谁没有?)像容易出错一样痛苦.

你知道IL Generator周围是否有一个好的包装器,我可以依赖它以比直接使用SRE更安全,更容易的方式发出IL吗?

编辑:

我知道操纵表达树比直接发射IL更容易和更安全,但它们现在也有一些限制.我不能创建代码块,使用循环,声明和使用几个本地,等等.我们需要等到.NET 4出来:)

此外,我正在处理已经依赖于SRE的代码库.

显然,ILGenerator会做我需要的一切.但是在操纵它时我会感激更多的帮助.当我指的是一个非常低级别的ILGenerator包装器时,我想到的东西可以提供如下方法:

// Performs a virtual or direct call on the method, depending if it is a 
// virtual or a static one.
Call(MethodInfo methodInfo)

// Pushes the default value of the type on the stack, then emit 
// the Ret opcode.
ReturnDefault(Type type)

// Test the object type to emit the corresponding push 
// opcode (Ldstr, Ldc_I*, Ldc_R*, etc.)
LoadConstant(object o)
Run Code Online (Sandbox Code Playgroud)

这真的是3个天真的例子,但它足以证明我的期望.我们可以看到它作为一组扩展方法,但是在RunSharp中支持条件语句和循环可能会很好.实际上,RunSharp与我想要的非常接近,但它过多地抽象了ILGenerator并且没有公开它的所有功能.

我不记得在哪里,但我已经在开源项目中看到过这样的帮手.

.net c# cil ilgenerator

7
推荐指数
1
解决办法
3547
查看次数

ILGenerator方法内联

给出以下代码:

using System;
using System.Reflection.Emit;
using System.Diagnostics;
using System.Reflection;

namespace ConsoleApplication1
{
    class A
    {
        public int Do(int n)
        {
            return n;
        }
    }

    public delegate int DoDelegate();

    class Program
    {
        public static void Main(string[] args)
        {
            A a = new A();

            Stopwatch stopwatch = Stopwatch.StartNew();
            int s = 0;
            for (int i = 0; i < 100000000; i++)
            {
                s += a.Do(i);
            }

            Console.WriteLine(stopwatch.ElapsedMilliseconds);
            Console.WriteLine(s);


            DynamicMethod dm = new DynamicMethod("Echo", typeof(int), new Type[] { typeof(int) }, true);
            ILGenerator il …
Run Code Online (Sandbox Code Playgroud)

.net methods cil inline ilgenerator

7
推荐指数
1
解决办法
1151
查看次数

如何根据IL动态编写带有Reflection.Emit的C#类

假设我们有一个接口:

public interface ICalculator
{
    decimal Calculate(decimal x, decimal y);
}
Run Code Online (Sandbox Code Playgroud)

计算逻辑是用javascript(实际上是TypeScript)代码实现的,我们想用Reflection.Emit动态创建跟随实现,所以我们可以用C#实现共享单元测试:

public class Calculator : ICalculator
{

    private ScriptEngine ScriptEngine;

    public Calculator(ScriptEngine scriptEngine, string jsFileFullPath)
    {
        this.ScriptEngine = scriptEngine;
        var jsFileContent = File.ReadAllText(jsFileFullPath);
        this.ScriptEngine.Execute(jsFileContent);
    }

    public decimal Calculate(decimal x, decimal y)
    {

        string script = @"
                var rf1013 = new TotalTaxation.TaxformCalculation.RF1013({0},{1});
                rf1013.Calculate();
                var result = rf1013.RF1013Sum;
            ";

        this.ScriptEngine.Evaluate(string.Format(script, x, y));

        var result = this.ScriptEngine.Evaluate("result");
        return Convert.ToDecimal(result);

    }
}
Run Code Online (Sandbox Code Playgroud)

我们可以从IL DASM获得IL:

.class public auto ansi beforefieldinit Calculator
       extends …
Run Code Online (Sandbox Code Playgroud)

c# il reflection.emit ilgenerator

6
推荐指数
1
解决办法
812
查看次数