Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过C#EMIT IL创建/分配对象_C#_.net_Reflection_Cil_Emit - Fatal编程技术网

通过C#EMIT IL创建/分配对象

通过C#EMIT IL创建/分配对象,c#,.net,reflection,cil,emit,C#,.net,Reflection,Cil,Emit,新到IL。。。正在尝试为以下对象创建IL: Dest CreateInstance(Source src) { Dest d = new Dest(); d.Test = src.Test; return d; } 这就是我到目前为止所做的: ConstructorInfo ctor = typeof(Dest).GetConstructors()[0]; DynamicMethod method = new DynamicMethod("CreateIntance", ty

新到IL。。。正在尝试为以下对象创建IL:

Dest CreateInstance(Source src)
{
   Dest d = new Dest();
   d.Test = src.Test;
   return d;
}
这就是我到目前为止所做的:

ConstructorInfo ctor = typeof(Dest).GetConstructors()[0];
DynamicMethod method = new DynamicMethod("CreateIntance", typeof(Dest),
    new Type[] { typeof(Source) });
ILGenerator gen = method.GetILGenerator();
//gen.Emit(OpCodes.Ldarg_0);// source
gen.Emit(OpCodes.Newobj, ctor);// new Created
gen.Emit(OpCodes.Ret);
CreateCtor createdCtorDelegate;
createdCtorDelegate = (CreateCtor)method.CreateDelegate(typeof(CreateCtor));
这运行如上所述。。。但是如果我取消对Ldarg_0的注释,当我尝试调用该委托时,我会得到一个“此操作可能会使运行时不稳定”

另外,复制测试成员需要什么?假设它是一个基本类型

谢谢

编辑:

Source和Dest以及简单的POCO

public class Source
{
    public string S1 { get; set; }
    public string S2 { get; set; }
    public int I1 { get; set; }
    public int I2 { get; set; }
    public string S3 { get; set; }
    public string S4 { get; set; }
    public string S5 { get; set; }
}

public class Dest
{
    public string S1 { get; set; }
    public string S2 { get; set; }
    public int I1 { get; set; }
    public int I2 { get; set; }
    public string S3 { get; set; }
    public string S4 { get; set; }
    public string S5 { get; set; }
}
编辑#2:现在,我有这个。。。仍然会得到去稳定化错误:

        ConstructorInfo ctor = typeof(Dest).GetConstructors()[0];
        DynamicMethod method = new DynamicMethod("CreateIntance", typeof(Dest),
            new Type[] { typeof(Source) });
        MethodInfo miSrc = tSource.GetProperty("S1").GetGetMethod();
        MethodInfo miDest = tDest.GetProperty("S1").GetSetMethod();

        ILGenerator gen = method.GetILGenerator();
        gen.Emit(OpCodes.Newobj, ctor);// new Created
        gen.Emit(OpCodes.Dup);
        gen.Emit(OpCodes.Ldarg_1);// source
        gen.Emit(OpCodes.Ldfld, miSrc);
        gen.Emit(OpCodes.Stfld, miDest);
        gen.Emit(OpCodes.Ret);
        CreateCtor createdCtorDelegate;
        createdCtorDelegate = (CreateCtor)method.CreateDelegate(typeof(CreateCtor));

        Dest dd = createdCtorDelegate(s);
调用createdCtorDelegate时获取异常

编辑3:

ILSpy显示:

.method public hidebysig static 
    class ConsoleApplication3.Dest Test (
        class ConsoleApplication3.Source s
    ) cil managed 
{
    // Method begins at RVA 0x2148
    // Code size 26 (0x1a)
    .maxstack 2
    .locals init (
        [0] class ConsoleApplication3.Dest,
        [1] class ConsoleApplication3.Dest
    )

IL_0000: nop
IL_0001: newobj instance void ConsoleApplication3.Dest::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldarg.0
IL_0009: callvirt instance string ConsoleApplication3.Source::get_S1()
IL_000e: callvirt instance void ConsoleApplication3.Dest::set_S1(string)
IL_0013: nop
IL_0014: ldloc.0
IL_0015: stloc.1
IL_0016: br.s IL_0018

IL_0018: ldloc.1
IL_0019: ret
} // end of method Program::Test
因此,我已将代码调整为:

        ConstructorInfo ctor = typeof(Dest).GetConstructors()[0];
        DynamicMethod method = new DynamicMethod("CreateIntance", typeof(Dest),
            new Type[] { typeof(Source) });
        MethodInfo miSrc = tSource.GetProperty("S1").GetGetMethod();
        MethodInfo miDest = tDest.GetProperty("S1").GetSetMethod();

        ILGenerator gen = method.GetILGenerator();

        gen.Emit(OpCodes.Newobj, ctor);// new Created
        gen.Emit(OpCodes.Stloc_0);
        gen.Emit(OpCodes.Ldloc_0);
        gen.Emit(OpCodes.Ldarg_0);
        gen.Emit(OpCodes.Callvirt, miSrc);
        gen.Emit(OpCodes.Callvirt, miDest);
        gen.Emit(OpCodes.Ldloc_0);
        gen.Emit(OpCodes.Stloc_1);
        gen.Emit(OpCodes.Ldloc_1);
        gen.Emit(OpCodes.Ret);

        CreateCtor createdCtorDelegate;
        createdCtorDelegate = (CreateCtor)method.CreateDelegate(typeof(CreateCtor));
仍在崩溃:(

…但是如果我取消对Ldarg\u 0的注释

您的方法应该返回一个值,这意味着当到达
ret
指令时,堆栈必须只包含一个项。
newobj
指令将创建新对象并将对它的引用加载到堆栈中,因此如果您在到达
ret
指令之前向堆栈中添加更多项而不使用它们,那么您的代码无效

复制测试成员需要什么

获取有效IL指令的最快方法是使用高级语言以及编译器和反编译器。 当您这样做时,您将得到如下结果:

IL_0000: newobj instance void Dest::.ctor() //create the new object
IL_0005: dup                                //duplicate the reference
IL_0006: ldarg.1                            //load the object to copy from
IL_0007: ldfld object Source::Test          //load the value from the old objects field
IL_000c: stfld object Dest::Test            //safe the value to the new objects field
IL_0011: ret                                //one reference of the new object is still on the stack

您的上一个代码接近正确,您只需声明要使用的局部变量:

ILGenerator gen = method.GetILGenerator();
gen.DeclareLocal(typeof(Dest));
还请注意,最后一对
stloc.1
ldloc.1
是不必要的,并且是在调试模式下编译代码的结果。检查CIL时,请始终在发行版中编译代码,因为代码更短,更易于阅读

您的第二个版本的方法也几乎正确,问题在于:

gen.Emit(OpCodes.Ldarg_1);// source
没有“参数1”,因为参数列表从0开始(对于静态方法,实例方法将
this
作为参数0)。解决方法很简单:

gen.Emit(OpCodes.Ldarg_0);// source

你能指定“基本类型”吗?你是指基元类型或结构还是…?你是否知道,如果表达式树存在,反射发射几乎是过时的?Protip:将IL转储到一个文件并对其运行PEVerify。你能在主要帖子中看到更新吗?我遵循了你的操作码,但仍然得到去稳定化错误。你使用的是属性,而不是像我一样的字段,请使用decompiler并查看通过属性发出的内容,它应该是
callvirt
操作码,并将set/get方法作为操作数。您使用的调试构建引入了局部变量,但没有声明这些变量。请查看
.locals init
语句。okaaay…因此我在发布模式下重建了,代码与您的代码非常相似已经发布,现在可以使用了:)谢谢!。。。最后一个问题。。。如果我编写一个硬编码方法并构建它,它的运行速度是这个动态方法的两倍。如果我编译一个动态DLL,它的运行速度也会加倍。。。为什么,当我发出与编译器完全相同的代码时,它的运行速度要慢得多?我认为这取决于你如何度量它。您是否创建了一个委托,并让运行时有机会在调用方法之前jit编译您的方法(通过在测量之前调用它)?