一、反射的使用 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。 需要使用的命名空间:System.Reflection 反射的作用很多,下面的例子主要是看一下怎么动态的调用类中的方法。 例子类 class ReflTest1 { private string _prop1; public string Prop1 { get { return _prop1; } set { _prop1 = value; } } public void Write1(string strText) { Console.WriteLine("111111111:" + strText); } public void Write2(string strText) { Console.WriteLine("222222222:" + strText); } public void MyWrite(string strText) { Console.WriteLine("3333333333:" + strText); } } 这个例子中提供了三个方法和一个属性,下面的代码来动态的调用它们: string strText = "abcd"; BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly); Type t = typeof(ReflTest1); MethodInfo[] mi = t.GetMethods(flags); Object obj = Activator.CreateInstance(t); foreach (MethodInfo m in mi) { if (m.Name.StartsWith("Write")) { m.Invoke(obj, new object[] { strText }); } } MethodInfo mMy = t.GetMethod("MyWrite"); if (mMy != null) { mMy.Invoke(obj, new object[] { strText }); } BindingFlags用来设置要取得哪些类型的方法,然后我们就可以取得这些方法来动态的调用。(当然为了可以循环的调用方法,在方法的命名方面可以自己指定一个规则) 二、动态生成类 我们可以在程序运行过程中调用.NET中提供的编译类,动态的将一段string编译成一个类,然后再通过反射来调用它 需要使用的命名空间:System.CodeDom System.CodeDom.Compiler Microsoft.CSharp System.Reflection 动态创建、编译类的代码如下: public static Assembly NewAssembly() { //创建编译器实例。 provider = new CSharpCodeProvider(); //设置编译参数。 paras = new CompilerParameters(); paras.GenerateExecutable = false; paras.GenerateInMemory = true; //创建动态代码。 StringBuilder classSource = new StringBuilder(); classSource.Append("public class DynamicClass \n"); classSource.Append("{\n"); //创建属性。 classSource.Append(propertyString("aaa")); classSource.Append(propertyString("bbb")); classSource.Append(propertyString("ccc")); classSource.Append("}"); System.Diagnostics.Debug.WriteLine(classSource.ToString()); //编译代码。 CompilerResults result = provider.CompileAssemblyFromSource(paras, classSource.ToString()); //获取编译后的程序集。 Assembly assembly = result.CompiledAssembly; return assembly; } private static string propertyString(string propertyName) { StringBuilder sbProperty = new StringBuilder(); sbProperty.Append(" private int _" + propertyName + " = 0;\n"); sbProperty.Append(" public int " + "" + propertyName + "\n"); sbProperty.Append(" {\n"); sbProperty.Append(" get{ return _" + propertyName + ";} \n"); sbProperty.Append(" set{ _" + propertyName + " = value; }\n"); sbProperty.Append(" }"); return sbProperty.ToString(); }propertyString方法就是用来拼写字符串的 整个代码比较简单,主要步骤就是:1、拼写类的字符串 2、调用CSharpCodeProvider类进行编译得到程序集(assembly) 接下来就可以利用之前反射的方法来动态调用这个类中的属性了: Assembly assembly = NewAssembly(); object Class1 = assembly.CreateInstance("DynamicClass"); ReflectionSetProperty(Class1, "aaa", 10); ReflectionGetProperty(Class1, "aaa"); object Class2 = assembly.CreateInstance("DynamicClass"); ReflectionSetProperty(Class1, "bbb", 20); ReflectionGetProperty(Class1, "bbb"); DynamicClass是我动态类的类名,aaa和bbb是其中的属性 ReflectionSetProperty和ReflectionGetProperty代码如下: 给属性赋值 private static void ReflectionSetProperty(object objClass, string propertyName, int value) { PropertyInfo[] infos = objClass.GetType().GetProperties(); foreach (PropertyInfo info in infos) { if (info.Name == propertyName && info.CanWrite) { info.SetValue(objClass, value, null); } } } 取得属性的值 private static void ReflectionGetProperty(object objClass, string propertyName) { PropertyInfo[] infos = objClass.GetType().GetProperties(); foreach (PropertyInfo info in infos) { if (info.Name == propertyName && info.CanRead) { System.Console.WriteLine(info.GetValue(objClass, null)); } } }
属性的赋值应该可以这样写:
PropertyInfo _Property = objClass.GetType().GetProperty(propertyName);
if (_Property != null && _Property.CanRead)
{
_Property.SetValue(objClass, value, null);
}
取得应该可以这样写:
PropertyInfo _Property = objClass.GetType().GetProperty(propertyName);
if (_Property != null && _Property.CanWrite)
{
_Property.GetValue(objClass, null);
}