【发布时间】:2018-08-16 22:02:50
【问题描述】:
您好,我想知道如何在不使用反射的情况下调用尚未存在的类的方法。如您所见,我正在使用生成器类 Weaver(使用 Reflection.Emit)返回一个Func<object>(我无法指定动态类型)。当我检索实例时,我将如何调用它的方法之一,特别是DoInt?
我想要自动生成
class Gen {
public Gen() {
}
public int DoInt(int a,string b) {
int rez=a+b.count();
return 3;
}
}
生成器类
class Weaver {
public static Func<object> Weave() {
var weaver = new Weaver();
weaver.Run();
return weaver.output as Func<object>;
}
private AssemblyBuilder assemblyBuilder;
private ModuleBuilder moduleBuilder;
private TypeBuilder typebuilder;
private object output;
public Weaver() {
}
private void Run() {
this.DefineAssembly();
this.DefineModule();
this.DefineClass();
this.DefineMethod();
this.Wrap();
}
private void DefineAssembly() {
AssemblyName name = new AssemblyName("Coda");
AppDomain domain = AppDomain.CurrentDomain;
assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndCollect);
}
private void DefineModule() {
this.moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyBuilder.FullName + ".dll");
}
private void DefineClass() {
this.typebuilder = this.moduleBuilder.DefineType("A",
TypeAttributes.Abstract|TypeAttributes.Public|TypeAttributes.BeforeFieldInit|TypeAttributes.AnsiClass|TypeAttributes.AutoClass,
typeof(object), null );
}
private void DefineMethod() {
MethodBuilder methodBuilder = this.typebuilder.DefineMethod("DoInt", MethodAttributes.Public, typeof(int), new[] { typeof(int), typeof(string) });
var il = methodBuilder.GetILGenerator();
il.Emit(OpCodes.Ldarg_1);
il.EmitCall(OpCodes.Call, typeof(Enumerable).GetMethod("Count", BindingFlags.Static), null);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Ret);
}
private void Wrap() {
Type type = typebuilder.CreateType();
this.output = Activator.CreateInstance(type);
}
}
主要
static void Main(string[] args)
{
string t = "astada";
var c = Weaver.Weave();
var result=c.GetType().GetMethod("DoInt").Invoke(null, new object[] { 3, "mystring" }); //should be 3+ "mystring".Count()
Console.ReadLine();
}
【问题讨论】:
-
weaver.output 是
object,而不是Func<object>,所以这是一种尽早卡住的方法。规范化代码也可能不会有什么坏处,例如,没有令人信服的理由使 DoInt() 成为实例方法。也许,当然,你更喜欢Func<object>,所以实际上用 MethodBuilder.CreateDelegate() 返回一个。当然你更喜欢Func<T>,所以它适用于任何类型,所以让类通用。
标签: c# reflection.emit