问题描述
在这一行抛出异常:
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" });