反射生成数组

两个月前写了一篇《对泛型进行反射》的文章,没什么人看,小伤心一下:(
今天在论坛有人问怎样反射生成数组,突然又来了兴致,决定试试
其实反射数组最难无非就是数组的初始化和数组的索引了,那么,如何初始化一个数组呢,数组是没有构造函数的,那么用 InvokeMember( null ,BindingFlags.DeclaredOnly| BindingFlags.Public|BindingFlags.NonPublic| BindingFlags.Instance|BindingFlags.CreateInstance,null,null,newobject[]{})
是肯定不行的,用GetMethods来看看,这个类型都有哪些方法,
  1. Typet=Type.GetType("System.Int32[]");
  2. foreach(MethodInfomiint.GetMethods(BindingFlags.Public|BindingFlags.Instance))
  3. {
  4. Console.WriteLine(mi.Name);
  5. }
结果如下:


我们看到,有一个名为Set的方法,这个会不会就是呢?
那我们来调用一下看看:
  1. Typet=Type.GetType("System.Int32[]");
  2. int[]array=newint[10];//初始化数组长度为10
  3. array=(int[])(t.InvokeMember("Set",BindingFlags.CreateInstance,null,array,newobject[]{5}));//这里将它的长度变为5看看是否能成功
  4. Console.WriteLine(array.Length);
可以看到,输出结果为5,这证明,的确是用Set方法来初始化数组的。
接下来,我们就会想,如何为数组的元素赋值及如何获取它们的值呢?
再次看一下上面的方法列表,可以看到有GetValue与SetValue方法,那我们来试试:
  1. Typet=Type.GetType("System.Int32[]");
  2. objectarray=newobject();
  3. array=t.InvokeMember("Set",BindingFlags.CreateInstance,null,array,newobject[]{10});
  4. for(inti=0;i<10;i++)
  5. t.GetMethod("SetValue",newType[2]{typeof(object),typeof(int)}).Invoke(array,newobject[]{i,i});
  6. for(inti=0;i<10;i++)
  7. Console.WriteLine(t.GetMethod("GetValue",newType[]{typeof(int)}).Invoke(array,newobject[]{i}));
结果如下:

调用成功,其实还是比较简单的。
可以看到,GetValue与SetValue有多个重载版本,如果想要反射多维数组,就要用到不同的重载,有兴趣的朋友可以自己试试。
<think>嗯,用户问的是C#反射生成对象,我得先回忆一下反射的基本概念。反射在C#里是用来在运行时获取类型信息,动态创建对象、调用方法或访问属性的一种机制。生成对象的话,主要应该是用Type类里的方法,比如Activator.CreateInstance或者ConstructorInfo.Invoke。 首先,得确定用户的需求层次。可能用户已经了解基础的对象创建方式,现在想深入动态生成实例的方法。可能需要分步骤说明,比如获取类型、选择构造函数、传递参数等。 然后,要考虑到不同情况,比如无参数构造和有参数构造的处理。Activator.CreateInstance比较方便,但参数构造时可能需要用Type.GetConstructor来获取特定构造函数。还要提醒异常处理,因为反射可能抛出MissingMethodException或TargetInvocationException。 另外,性能问题也很重要,反射创建对象比直接new要慢,如果频繁使用可能需要考虑其他方式,比如表达式树或者缓存ConstructorInfo。不过用户的问题主要是生成对象,可能暂时不需要深入优化部分,但可以稍微提一下。 还有,是否需要举例说明?比如一个简单的类,然后演示用反射创建。代码示例应该用中文注释,符合用户要求。同时注意代码中的类型获取方式,比如typeof或者Type.GetType,以及程序集相关的内容,如果类型在不同程序集中可能需要处理Assembly加载。 可能用户在使用过程中会遇到类型找不到的情况,需要确保类型名称正确,区分命名空间。另外,参数数组的构建,特别是值类型参数需要注意装箱,比如int要转换成object数组的元素。 最后,总结一下步骤,并强调反射的灵活性和代价,帮助用户权衡使用场景。检查是否有遗漏的关键点,比如私有构造函数的处理,是否需要BindingFlags来指定非公共成员,不过一般情况可能用公共构造函数,但可以提到这点扩展用户的了解。</think>在C#中,通过反射动态生成对象是一个重要的高级特性。以下是逐步说明: 一、反射基础概念 反射(Reflection)是.NET框架提供的一种机制,允许在运行时: 1. 获取类型信息(类、结构体等) 2. 动态创建对象实例 3. 访问和操作成员(属性/方法/字段) 二、核心步骤 1. 获取类型信息 ```csharp // 通过类型名称获取 Type type = Type.GetType("命名空间.类名"); // 通过已有对象获取 Type type = existingObject.GetType(); // 通过typeof运算符 Type type = typeof(目标类型); ``` 2. 创建对象实例 - 无参数构造: ```csharp object obj = Activator.CreateInstance(type); ``` - 带参数构造: ```csharp object[] parameters = { 参数1, 参数2 }; object obj = Activator.CreateInstance(type, parameters); ``` 3. 通过构造函数信息创建(更灵活) ```csharp ConstructorInfo ctor = type.GetConstructor(new[] { typeof(参数类型1), typeof(参数类型2) }); object obj = ctor.Invoke(new object[] { 参数值1, 参数值2 }); ``` 三、代码示例 ```csharp public class Person { public string Name { get; set; } public Person() { } public Person(string name) { Name = name; } } // 反射创建实例 Type personType = typeof(Person); // 无参构造 object person1 = Activator.CreateInstance(personType); // 带参构造 object person2 = Activator.CreateInstance(personType, "张三"); // 通过ConstructorInfo ConstructorInfo ctor = personType.GetConstructor(new[] { typeof(string) }); object person3 = ctor.Invoke(new object[] { "李四" }); ``` 四、注意事项 1. 异常处理 - `MissingMethodException`: 没有匹配的构造函数 - `TargetInvocationException`: 构造函数抛出异常 2. 性能考量 反射操作比直接实例化慢约50-100倍,高频场景建议: - 缓存`Type`/`ConstructorInfo`对象 - 使用`dynamic`类型(.NET 4.0+) - 使用表达式树编译 3. 权限要求 需要适当的代码访问安全权限,在部分受限制环境中可能无法使用 五、典型应用场景 1. 依赖注入框架的对象实例化 2. 插件系统动态加载 3. ORM映射数据到实体 4. 序列化/反序列化操作 六、进阶技巧 1. 创建泛型类型实例: ```csharp Type genericType = typeof(List<>).MakeGenericType(typeof(int)); object list = Activator.CreateInstance(genericType); ``` 2. 处理私有构造函数: ```csharp ConstructorInfo privateCtor = type.GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null); ``` 建议根据具体需求选择合适的方式,在灵活性和性能之间取得平衡。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值