Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.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# 如何在反射发射类中发射局部变量init([0]字符串V_0)?_C#_.net_Reflection.emit - Fatal编程技术网

C# 如何在反射发射类中发射局部变量init([0]字符串V_0)?

C# 如何在反射发射类中发射局部变量init([0]字符串V_0)?,c#,.net,reflection.emit,C#,.net,Reflection.emit,它会在此行中引发异常: s = method.Invoke(student, new object[] { "pig" }); 下面是完整的代码,您可以创建一个新的.net framewrok控制台应用程序并运行它 public class Program { static void Main(string[] args) { MethodInfo method = typeof(Student).GetMet

它会在此行中引发异常:

s = method.Invoke(student, new object[] { "pig" });
下面是完整的代码,您可以创建一个新的.net framewrok控制台应用程序并运行它

public class Program
    {
        static void Main(string[] args)
        {
            MethodInfo method = typeof(Student).GetMethod("SayHello");

            var student1 = new Student("lucy");
            object s = method.Invoke(student1, new object[] { "pig" });

            var student = BuildType(typeof(Person));
            //todo:throw an exception here ??
            s = method.Invoke(student, new object[] { "pig" });

            Console.ReadKey();
        }

        public static object BuildType(Type baseType)
        {
            AppDomain dom = AppDomain.CurrentDomain;
            AssemblyName asmName = new AssemblyName("DynamicAssembly");
            AssemblyBuilder assemblyBuilder = dom.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);

            //AssemblyName DemoName = new AssemblyName("DynamicAssembly");
            //AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(DemoName, AssemblyBuilderAccess.RunAndSave);

            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("LjxModule", "LjxModule.dll");
            //dynamicly create Class
            TypeBuilder tb = moduleBuilder.DefineType("MyStudent", TypeAttributes.Public, baseType);
            Type[] ctorPaTypes = new Type[] { typeof(string) };

            ConstructorBuilder ctorBuilder = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard | CallingConventions.HasThis, ctorPaTypes);
            ILGenerator msilGenerator = ctorBuilder.GetILGenerator();
            msilGenerator.Emit(OpCodes.Ldarg_0);//push this
            msilGenerator.Emit(OpCodes.Ldarg_1);
            ConstructorInfo baseCtor = baseType.GetConstructor(ctorPaTypes);
            if (baseCtor == null)
            {
                throw new Exception("some exception!");
            }
            msilGenerator.Emit(OpCodes.Call, baseCtor);
            msilGenerator.Emit(OpCodes.Nop);
            msilGenerator.Emit(OpCodes.Nop);
            msilGenerator.Emit(OpCodes.Ret);

            //override method
            MethodBuilder executeAsyncMethod = tb.DefineMethod("SayHello", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, typeof(string),
                new Type[] { typeof(object) });
            MethodInfo baseMethodInfo = baseType.GetMethod("SayHello", new Type[] { typeof(object) });
            if (baseMethodInfo == null)
            {
                throw new Exception("some exception!");
            }
            ILGenerator ilGen = executeAsyncMethod.GetILGenerator();
            var mylabel = ilGen.DefineLabel();

            //todo:this line code emit:      .locals init (string[] V_0)
            //but i found Student class' il is:     .locals init ([0] string V_0)
            var v1 = ilGen.DeclareLocal(typeof(string));

            ilGen.Emit(OpCodes.Nop);
            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldarg_1);
            ilGen.Emit(OpCodes.Call, baseMethodInfo);
            ilGen.Emit(OpCodes.Stloc_0);
            ilGen.Emit(OpCodes.Br_S, mylabel);
            ilGen.MarkLabel(mylabel);
            ilGen.Emit(OpCodes.Ldloc_0);
            ilGen.Emit(OpCodes.Ret);

            if (baseMethodInfo == null)
            {
                throw new Exception("some exception!");
            }
            
            //tb.DefineMethodOverride(executeAsyncMethod, baseMethodInfo);

            Type resultType = tb.CreateType();

            //save dll
            assemblyBuilder.Save("LjxModule.dll");

            //create instance
            var arg0 = "jacks";
            if (resultType == null)
            {
                throw new Exception("some exception!");
            }
            return Activator.CreateInstance(resultType, arg0);
        }

        public static Type SingleTypeByQualifiedName(string assemblyQualifiedName)
        {
            Type paramType = Type.GetType(assemblyQualifiedName);
            if (paramType == null)
            {
                throw new Exception($"not found {assemblyQualifiedName}!");
            }
            return paramType;
        }
    }

    public class Person
    {
        public Person(string name)
        {
            Name = name;
        }
        public string Name { get; set; }

        public virtual string SayHello(object obj)
        {
            return Name + "say:" + obj.ToString();
        }
    }

    public class Student : Person
    {
        public Student(string name) : base(name)
        {
        }

        public override string SayHello(object obj)
        {
            return base.SayHello(obj);
        }
    }
这是发射的IL:

.method public hidebysig virtual instance string SayHello(object A_1) cil managed
{
  // 代码大小       13 (0xd)
  .maxstack  3
  .locals init (string[] V_0)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldarg.1
  IL_0003:  call       instance string [DotFxConsoleApp1]DotFxConsoleApp1.Model.Person::SayHello(object)
  IL_0008:  stloc.0
  IL_0009:  br.s       IL_000b
  IL_000b:  ldloc.0
  IL_000c:  ret
} // end of method MyStudent::SayHello
这是学生班的IL

.method public hidebysig virtual instance string SayHello(object obj) cil managed
{
  // 代码大小       13 (0xd)
  .maxstack  2
  .locals init ([0] string V_0)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldarg.1
  IL_0003:  call       instance string DotFxConsoleApp1.Model.Person::SayHello(object)
  IL_0008:  stloc.0
  IL_0009:  br.s       IL_000b
  IL_000b:  ldloc.0
  IL_000c:  ret
} // end of method Student::SayHello

看起来唯一的区别是.locals init(string[]V_0),如何修复它?谁能帮我一下吗?多谢各位

我知道原因。我犯了一个错误。我使用Student.SayHello MethodInfo调用MyStudent实例。我已经更正了代码,现在它运行良好

MethodInfo method = typeof(Student).GetMethod("SayHello");

            var student1 = new Student("lucy");
            object s = method.Invoke(student1, new object[] { "pig" });

            var myStuType = BuildType(typeof(Person));
            MethodInfo dyMethod = myStuType.GetMethod("SayHello");
            var student = Activator.CreateInstance(myStuType, new string[] { "jack" });
            s = dyMethod.Invoke(student, new object[] { "pig" });

这并不重要,但最好是执行
ilGen.Emit(OpCodes.Stloc,v1),而不是猜测插槽的编号。试一试,看看它是否有任何区别。你有哪个版本的.NET?谢谢你的canton7和Charlieface。我知道原因。我犯了一个错误