【整理】C#反射总结

C#反射机制详解

1.使用反射获取类型
方法1:Type t=对象.GetType();
方法2:Type t=Type.GetType("System.String"),参数为在mscorlib.dll程序集中的类或者当前程序集中的类
如果要获得其他程序集中的类型,情况1:若要使用Type.GetType方法,则参数要指明该类型所在的程序集,如:获取System.Data.DataTable,代码如下

Type t = Type.GetType("System.Data.DataTable,System.Data,Version=1.0.3300.0,   Culture=neutral,   PublicKeyToken=b77a5c561934e089");

情况2:或者使用先加载所要调用的类型所在的程序集,再获取,如:A.dll要获取B.dll中的类型,代码如下

Assembly assembly = Assembly.LoadFrom(@"D:\MyPrograme\MyRelect\Bin\B.dll");
//获取类型信息
Type t = assembly.GetType("B.ReflectionTest");//为程序集名+类名

注意此时LoadFrom为全路径

额外提一下:

1)、Assembly.LoadFile只载入相应的dll文件,比如Assembly.LoadFile("abc.dll"),则载入abc.dll,假如abc.dll中引用了def.dll的话,def.dll并不会被载入。
Assembly.LoadFrom则不一样,它会载入dll文件及其引用的其他dll,比如上面的例子,def.dll也会被载入。

2)、用Assembly.LoadFrom载入一个Assembly时,会先检查前面是否已经载入过相同名字的Assembly,
比如abc.dll有两个版本(版本1在目录1下,版本2放在目录2下),程序一开始时载入了版本1,当使用Assembly.LoadFrom("2\\abc.dll")载入版本2时,不能载入,而是返回版本1。Assembly.LoadFile的话则不会做这样的检查,比如上面的例子换成Assembly.LoadFile的话,则能正确载入版本2。

2.判断类型是否实现了某个接口
t.GetInterface("接口名称")
3.根据类型动态创建对象
System.Activator提供了方法来根据类型动态创建对象
DataTable table=(DataTable)Activator.CreateInstance(t);
Type t=Type.GetType("TestSpace.TestClass");
Object[] constructParams=new object[]{"hello"};
TestClass obj=(TestClass)Activator.CreateInstance(t,constructParams);

4.如何获取方法以及动态调用方法

        Assembly assembly = Assembly.LoadFrom(@"D:\MyPrograme\MyRelect\Bin\ClassReflect.dll");
        
//获取类型信息
        Type t = assembly.GetType("ClassReflect.ReflectionTest");
        
//构造器的参数
        object[] constructParams = new object[] { "timmy" };
        
//根据类型创建对象
        object dObj = Activator.CreateInstance(t, constructParams);
        
//获取方法的信息
        MethodInfo method = t.GetMethod("GetValue");
        
//调用方法的一些标志位,这里的含义是Public并且是实例方法,这也是默认的值
        BindingFlags flag = BindingFlags.Public | BindingFlags.Instance;
        
//GetValue方法的参数
        object[] parameters = new object[] { "hello" };
        
//调用方法,用一个object接收返回值
        object returnValue = method.Invoke(dObj, flag, Type.DefaultBinder, parameters, null);

 

转载于:https://www.cnblogs.com/hinroe/archive/2010/04/18/1715034.html

<think>好的,我现在需要回答用户的问题,关于如何使用C#反射机制给私有或公共字段动态赋值,并提供示例代码。首先,我得回忆一下反射的基本概念和相关类。反射C#中主要通过System.Reflection命名空间下的类来实现,比如Type、PropertyInfo、FieldInfo等。用户提到的是给字段赋值,所以应该关注FieldInfo类。 用户的问题包括私有和公共字段的动态赋值,所以需要区分字段的访问权限。公共字段可能不需要特别处理,而私有字段需要设置BindingFlags来访问。根据引用中的示例,比如引用[4]提到使用BindingFlags.NonPublic来获取私有字段,这应该是一个关键点。 接下来,我需要考虑如何获取类型信息。通常使用typeof(类名)或者实例的GetType()方法。例如,引用[2]中的代码使用了instance.GetType().GetProperties(),但这里需要处理的是字段而不是属性,所以应该用GetFields方法,不过需要注意默认情况下GetFields不会返回私有字段,除非指定BindingFlags。 然后,设置字段的值需要使用FieldInfo的SetValue方法。对于静态字段和实例字段,调用方式可能不同。用户的问题应该是指实例字段,因此需要传递对象实例作为参数。例如,引用[4]中的代码m_colliders.SetValue(t, colliders);,其中t是实例。 现在,我需要构建一个示例类,包含私有和公共字段,然后演示如何通过反射赋值。比如定义一个Student类,有私有字段_privateField和公共字段publicField。然后编写代码获取这些字段并设置它们的值。 需要注意的是,获取私有字段时,BindingFlags应该包括Instance | NonPublic,而公共字段可能需要Instance | Public。同时,GetField方法可能需要指定确切的绑定标志,否则可能找不到字段。例如,引用[4]中使用了多个BaseType来定位父类的字段,但当前问题可能不需要处理继承层次,所以可以暂时忽略。 然后,处理静态字段的情况。静态字段不需要实例,所以传递null作为SetValue的第一个参数。例如,设置静态字段_staticField的值时,使用field.SetValue(null, value)。 还要考虑安全性和权限问题,反射访问私有成员可能需要适当的权限,但在大多数情况下,只要代码有足够的信任级别就可以执行。 现在,综合这些步骤,可以编写示例代码。首先定义测试类,然后获取类型,检索字段,设置字段的值,最后验证结果。同时,需要处理可能出现的异常,比如字段不存在的情况,但示例中可以简化处理。 最后,根据用户提供的引用,尤其是引用[2]和[4],需要确保代码中使用正确的BindingFlags组合,比如BindingFlags.Instance | BindingFlags.NonPublic等。例如,引用[2]中获取属性时使用了GetProperties(),而这里需要获取字段,所以使用GetField方法并指定正确的标志。 总结步骤: 1. 定义包含私有和公共字段的类。 2. 使用Type.GetField或Type.GetFields获取字段信息,指定BindingFlags。 3. 使用FieldInfo.SetValue方法赋值,传递实例和值。 4. 处理静态字段时,传递null作为实例。 5. 输出结果以验证赋值成功。 可能需要测试不同的BindingFlags组合,例如对于公共字段,使用Public | Instance,对于私有字段使用NonPublic | Instance。如果GetField找不到字段,可能需要检查是否遗漏了BindingFlags中的某些标志,比如DeclaredOnly等。 现在将这些思考整理成结构化的回答,确保示例代码正确,并解释每个步骤的作用,同时引用相关的参考资料中的方法,比如引用[4]中关于使用BaseType来访问父类字段,但当前问题可能不需要,所以可能不涉及。但用户的问题主要关注如何给当前类的私有或公共字段赋值,因此重点放在正确的BindingFlags使用上。</think>以下是使用C#反射机制动态给字段赋值的分步说明及示例代码: ### 一、反射赋值核心方法 通过`System.Reflection`命名空间实现,关键点在于: 1. 使用`Type.GetField()`获取字段信息 2. 设置`BindingFlags`突破访问限制 3. 调用`FieldInfo.SetValue()`赋值 ### 二、完整示例代码 ```csharp using System; using System.Reflection; public class Student { // 测试字段定义 private int _privateField = 10; public string publicField = "原始值"; private static string _staticField = "静态字段"; } class Program { static void Main() { var instance = new Student(); // 1. 给私有实例字段赋值 FieldInfo privateField = typeof(Student).GetField("_privateField", BindingFlags.Instance | BindingFlags.NonPublic); privateField.SetValue(instance, 999); Console.WriteLine($"私有字段值:{privateField.GetValue(instance)}"); // 2. 给公共实例字段赋值 FieldInfo publicField = typeof(Student).GetField("publicField"); publicField.SetValue(instance, "修改后的值"); Console.WriteLine($"公共字段值:{instance.publicField}"); // 3. 给私有静态字段赋值 FieldInfo staticField = typeof(Student).GetField("_staticField", BindingFlags.Static | BindingFlags.NonPublic); staticField.SetValue(null, "修改后的静态值"); Console.WriteLine($"静态字段值:{staticField.GetValue(null)}"); } } ``` ### 三、关键参数说明 1. **BindingFlags组合**: - 私有字段:`NonPublic | Instance`(实例字段)或`NonPublic | Static`(静态字段) - 公共字段:默认包含`Public`标志,可省略 2. **多级继承处理**: 若字段定义在父类中,需通过`Type.BaseType`逐级查找(如引用[4]所示) 3. **安全验证**: 可通过`fieldInfo.IsPublic`判断字段访问性,`fieldInfo.IsStatic`判断是否静态 ### 四、执行结果 ``` 私有字段值:999 公共字段值:修改后的值 静态字段值:修改后的静态值 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值