关于C#利用反射动态创建类并调用

BreakAndUp 2017-03-24 09:34:29

class Program
{
static void Main(string[] args)
{
//动态创建的类类型
Type classType = DynamicCreateType();
//调用有参数的构造函数
Type[] ciParamsTypes = new Type[] { typeof(string) };
object[] ciParamsValues = new object[] { "Hello World!!!" };
ConstructorInfo ci = classType.GetConstructor(ciParamsTypes);
object Vector = ci.Invoke(ciParamsValues);
//调用方法
object[] methodParams = new object[] { };
Console.WriteLine(classType.InvokeMember("get_Field", BindingFlags.InvokeMethod, null, Vector, methodParams));
Console.ReadKey();
}

public static Type DynamicCreateType()
{
//动态创建程序集
AssemblyName DemoName = new AssemblyName("DynamicAssembly");
AssemblyBuilder dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName, AssemblyBuilderAccess.RunAndSave);
//动态创建模块
ModuleBuilder mb = dynamicAssembly.DefineDynamicModule(DemoName.Name, DemoName.Name + ".dll");
//动态创建类MyClass
TypeBuilder tb = mb.DefineType("MyClass", TypeAttributes.Public);
//动态创建字段
FieldBuilder fb = tb.DefineField("myField", typeof(System.String), FieldAttributes.Private);
//动态创建构造函数
Type[] clorType = new Type[] { typeof(System.String) };
ConstructorBuilder cb1 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, clorType);
//生成指令
ILGenerator ilg = cb1.GetILGenerator();//生成 Microsoft 中间语言 (MSIL) 指令
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Ldarg_1);
ilg.Emit(OpCodes.Stfld, fb);
ilg.Emit(OpCodes.Ret);
//动态创建属性
PropertyBuilder pb = tb.DefineProperty("MyProperty", PropertyAttributes.HasDefault, typeof(string), null);
//动态创建方法
MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName;
MethodBuilder myMethod = tb.DefineMethod("get_Field", getSetAttr, typeof(string), Type.EmptyTypes);
//生成指令
ILGenerator numberGetIL = myMethod.GetILGenerator();
numberGetIL.Emit(OpCodes.Ldarg_0);
numberGetIL.Emit(OpCodes.Ldfld, fb);
numberGetIL.Emit(OpCodes.Ret);
//使用动态类创建类型
Type classType = tb.CreateType();
//保存动态创建的程序集 (程序集将保存在程序目录下调试时就在Debug下)
dynamicAssembly.Save(DemoName.Name + ".dll");
//创建类
return classType;
}
}

各位大神,这是网上复制的别人的代码,可以运行。我想求教以下几点:
1、如何创建多个属性,并调用?
2、DefineMethod(),DefineField()里面的参数都有什么用?
3、必须用Constructor才能进行实例化吗,为什么不能用new?
谢谢各位了。
...全文
306 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
游离失所 2017-03-24
  • 打赏
  • 举报
回复
1.
 static void Main(string[] args)
        {
            Type classType = DynamicCreateType();
            dynamic obj = classType.GetConstructor(Type.EmptyTypes).Invoke(new object[0]);
            obj.Name = "Tom";
            obj.Age = 13;
        }

        public static Type DynamicCreateType()
        {
            Dictionary<string, Type> properties = new Dictionary<string, Type>(){
                {"Name",typeof(string)},
                {"Age",typeof(int)}
            };

            AssemblyName DemoName = new AssemblyName("DynamicAssembly");
            AssemblyBuilder dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName, AssemblyBuilderAccess.RunAndSave);

            ModuleBuilder mb = dynamicAssembly.DefineDynamicModule(DemoName.Name, DemoName.Name + ".dll");
            TypeBuilder tb = mb.DefineType("MyClass", TypeAttributes.Public);
            ILGenerator il;
            foreach (var kv in properties)
            {
                FieldBuilder fb = tb.DefineField(string.Format("_{0}", kv.Key), kv.Value, FieldAttributes.Private);
                PropertyBuilder pb = tb.DefineProperty(kv.Key, PropertyAttributes.None, kv.Value, Type.EmptyTypes);
                MethodBuilder setMethod = tb.DefineMethod(string.Format("set_{0}", kv.Key), MethodAttributes.Public, typeof(void), new Type[] { kv.Value });
                il = setMethod.GetILGenerator();
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Stfld, fb);
                il.Emit(OpCodes.Ret);
                pb.SetSetMethod(setMethod);

                MethodBuilder getMethod = tb.DefineMethod(string.Format("get_{0}", kv.Key), MethodAttributes.Public, kv.Value, Type.EmptyTypes);
                il = getMethod.GetILGenerator();
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, fb);
                il.Emit(OpCodes.Ret);
                pb.SetGetMethod(getMethod);
            }
            return tb.CreateType();
        }
2.参数有什么用自己看啊。这个还要教吗? 3.是的。因为这个对象类型是运行时创建的。 其实new分两步。先是向操作系统申请类型大小的堆内存,操作系统返回一个首地址给你,然后这个地址放在栈上。然后调用构函数去初始化。 new是给编译器看的

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧