你混淆了產生程序之間的邊界,產生程序。
具體而言,您的生成程序在運行時會構造一個對象的實例(MethodInfo
實例),然後嘗試生成使用該實例的程序 - 它不能因爲該實例不存在於生成的程序,它存在於生成程序的內存中。
您必須在生成的程序中構建MethodInfo
的實例 - 您必須編寫發射代碼來生成構建MethodInfo
實例的IL。
什麼你正在試圖做的,使大約多大意義爲執行以下操作:
Person person = new Person("Antiduh", "United States");
var genericType = typeof(GenericType<>).MakeGenericType(typeof(TOutput));
il.Emit(OpCodes.Newobj, genericType.GetConstructor(Type.EmptyTypes));
// This doesn't make sense. The object referred to by
// my `person` variable doesn't exist in the generated program.
il.Emit(OpCodes.Ldobj, person);
il.Emit(OpCodes.Callvirt, genericeClientHelper.GetMethod("MethodName", new Type[] { typeof(MethodInfo) }));
il.Emit(OpCodes.Ret);
這就是問題的編號爲1
問題2號是您使用了錯誤的操作碼時,試圖提供一個方法的參數 - Ldobj
不會做你認爲它的作用。
而不是使用Ldobj
,您必須通過任何方式加載參考,您可以通過修復代碼來創建內部methodInfo
。它可能是本地的,所以你最終可能會使用Ldloc
或其某種形式。
爲了得到完整的圈子,你得到錯誤「Bad class token」的原因是在編譯的IL中應該遵循Ldobj
的值應該是類元數據令牌。你提供的不是一個類標記,因此是錯誤。
作爲一個演示,下面是一個模擬您正在嘗試執行的完整程序。
private static void BuildAssembly()
{
AssemblyName assemblyName;
AssemblyBuilder assmBuilder;
ModuleBuilder modBuilder;
assemblyName = new AssemblyName("Generated");
// Note the save directory is the directory containing this project's solution file.
assmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
assemblyName,
AssemblyBuilderAccess.RunAndSave,
Assembly.GetExecutingAssembly().Location + @"\..\..\..\.."
);
modBuilder = assmBuilder.DefineDynamicModule(
assemblyName.Name,
assemblyName.Name + ".dll",
true
);
/*
* public class GenericsDemo {
* }
*/
TypeBuilder typeBuilder = modBuilder.DefineType(
"Generated.GenericsDemo",
TypeAttributes.Public
);
BuildCallListMethod(typeBuilder);
typeBuilder.CreateType();
assmBuilder.Save(assemblyName.Name + ".dll");
}
private static void BuildCallListMethod(TypeBuilder typeBuilder)
{
// public void CallList() {
// List<object> list = new List<object>();
// object thing = new object();
// list.Add(thing);
// }
var listOfObject = typeof(List<object>);
var objType = typeof(object);
// public void CallList() {
var method = typeBuilder.DefineMethod(
"CallList",
MethodAttributes.Public | MethodAttributes.HideBySig,
CallingConventions.HasThis
);
var gen = method.GetILGenerator();
// List<int> list;
var listLocal = gen.DeclareLocal(listOfObject);
listLocal.SetLocalSymInfo("list");
// object thing;
var thingLocal = gen.DeclareLocal(objType);
thingLocal.SetLocalSymInfo("thing");
// list = new List<object>();
gen.Emit(OpCodes.Newobj, listOfObject.GetConstructor(Type.EmptyTypes));
gen.Emit(OpCodes.Stloc_0);
// thing = new object();
gen.Emit(OpCodes.Newobj, objType.GetConstructor(Type.EmptyTypes));
gen.Emit(OpCodes.Stloc_1);
// list.Add(thing);
gen.Emit(OpCodes.Ldloc_0); // loads `list`.
gen.Emit(OpCodes.Ldloc_1); // loads `thing`.
gen.EmitCall(OpCodes.Callvirt, listOfObject.GetMethod("Add"), null);
gen.Emit(OpCodes.Ret);
}
你能告訴我們更多的代碼嗎?比如,你如何構造這個類型,你如何定義這個方法?你當前的代碼看起來很好(雖然'genericeClientHelper.GetMethod'應該可能是'genericType.GetMethod',我相信。 – Rob