在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
最近想研究一下反射,先上网找了找资料,几乎大部分都是照抄MSDN的内容,生涩难懂,几乎没说,又找了找,发现一些强人的实例解析,才稍微有了点门道,个人感觉,反射其实就是为了能够在程序运行期间动态的加载一个外部的DLL集合,然后通过某种办法找到这个DLL集合中的某个空间下的某个类的某个成员(通过反射可以访问该类所包含的所有成员,不论成员是公有还是私有),看看网上N人写的实例:
namespace lab.CommonBasic.Common { class StringUtil { public double GetSum(double x, double y) { return x + y; } } } //这里要用LoadFrom,只有在本工程里添加了该dll的引用后才可以使用Load Assembly objAss = Assembly.LoadFrom(@"D:\Test\HSMP.CommonBasic.dll"); //HSMP.CommonBasic.Common.StringUtil类的全路径 Type t = objAss.GetType("HSMP.CommonBasic.Common.StringUtil"); //动态生成类StringUtil的实例 object obj = System.Activator.CreateInstance(t); //参数信息,GetSum需要两个int参数 System.Type[] paramTypes = new System.Type[2]; paramTypes[0] = System.Type.GetType("System.Int32"); paramTypes[1] = System.Type.GetType("System.Int32"); //找到对应的方法 MethodInfo p = t.GetMethod("SayHello", paramTypes); // 也可以不给类型参数,下面调用时给实参就可以 MethodInfo p = t.GetMethod("SayHello"); //参数值,如果所调用的方法没有参数,不用写这些 Object[] parameters = new Object[2]; parameters[0] = 3; parameters[1] = 4; //如果没有参数,写null即可。 object objRetval = p.Invoke(obj, parameters); 通过代码可以看出反射其实很简单。就是动态类型加载。
以上我们用反射对静态类型做加载,但如果类是个范型类该怎么办呢?其实方法大同小异,只是获取到类型时需要设置一下实际要使用的类型即可,先看范型类定义:
namespace lab.CommonBasic.Common { class StringUtil<T,U> { public string GetSum(T x, U y) { return x + " and " + y; } } } 再看反射操作: ... 前面代码相同 //HSMP.CommonBasic.Common.StringUtil类的全路径(范型类最后用 `2 标示需要2个范型类型参数) Type t = objAss.GetType("HSMP.CommonBasic.Common.StringUtil`2"); // 这一步很重要,设置实际的范型类型 t = t.MakeGenericType(new Type[2] { typeof(string), typeof(string) }); //动态生成类StringUtil的实例 object obj = System.Activator.CreateInstance(t); ... 后面代码相同
还有一种情况,如果类是常类,但方法是范型方法改怎么办?非常简单: ... 前面代码相同
//HSMP.CommonBasic.Common.StringUtil类的全路径(范型类最后用 `2 标示需要2个范型类型参数) Type t = objAss.GetType("HSMP.CommonBasic.Common.StringUtil`2"); // 这一步要去掉,因为类不是泛型类所以不能给类设置范型类型 //t = t.MakeGenericType(new Type[2] { typeof(string), typeof(string) }); ... 中间代码相同 // 区别在这里,把类级别的范型类型设置放到方法级别就可以了。
MethodInfo p = t.GetMethod("SayHello");
MethodInfo p = p.MakeGenericMethod(new Type[2] { typeof(string), typeof(string) }); ... 后面代码相同
class ChangeValue { // 这是私有字段 private string myValue; // 一般只有通过这样的公共属性外面才可能访问私有字段 public ChangeValue(string str) { myValue = str; } public void WriteLine() { Console.WriteLine("MyValue is: " + myValue); } } class Test { public static void Main(string[] args) { // 正常访问 ChangeValue cv = new ChangeValue("old value"); cv.WriteLine(); //反射的方法直接访问私有字段 Type t = cv.GetType(); //得到私有字段对象并赋值 FieldInfo field = t.GetField("myValue", BindingFlags.NonPublic | BindingFlags.Instance); field.SetValue(cv, "new value"); //输出的是新值 "new value" cv.WriteLine(); } }
|
请发表评论