- 一、反射的使用
- 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。
- 需要使用的命名空间:System.Reflection
- 反射的作用很多,下面的例子主要是看一下怎么动态的调用类中的方法。
- 例子类
- classReflTest1
- {
- privatestring_prop1;
- publicstringProp1
- {
- get{return_prop1; }
- set{ _prop1 = value; }
- }
- publicvoidWrite1(stringstrText)
- {
- Console.WriteLine("111111111:"+ strText);
- }
- publicvoidWrite2(stringstrText)
- {
- Console.WriteLine("222222222:"+ strText);
- }
- publicvoidMyWrite(stringstrText)
- {
- Console.WriteLine("3333333333:"+ strText);
- }
- }
- 这个例子中提供了三个方法和一个属性,下面的代码来动态的调用它们:
- stringstrText ="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 minmi)
- {
- if(m.Name.StartsWith("Write"))
- {
- m.Invoke(obj,newobject[] { strText });
- }
- }
- MethodInfo mMy = t.GetMethod("MyWrite");
- if(mMy !=null)
- {
- mMy.Invoke(obj,newobject[] { strText });
- }
- BindingFlags用来设置要取得哪些类型的方法,然后我们就可以取得这些方法来动态的调用。(当然为了可以循环的调用方法,在方法的命名方面可以自己指定一个规则)
- 二、动态生成类
- 我们可以在程序运行过程中调用.NET中提供的编译类,动态的将一段string编译成一个类,然后再通过反射来调用它
- 需要使用的命名空间:System.CodeDom System.CodeDom.Compiler Microsoft.CSharp System.Reflection
- 动态创建、编译类的代码如下:
- publicstaticAssembly NewAssembly()
- {
- //创建编译器实例。
- provider =newCSharpCodeProvider();
- //设置编译参数。
- paras =newCompilerParameters();
- paras.GenerateExecutable =false;
- paras.GenerateInMemory =true;
- //创建动态代码。
- StringBuilder classSource =newStringBuilder();
- 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;
- returnassembly;
- }
- privatestaticstringpropertyString(stringpropertyName)
- {
- StringBuilder sbProperty =newStringBuilder();
- 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(" }");
- returnsbProperty.ToString();
- }propertyString方法就是用来拼写字符串的
- 整个代码比较简单,主要步骤就是:1、拼写类的字符串 2、调用CSharpCodeProvider类进行编译得到程序集(assembly)
- 接下来就可以利用之前反射的方法来动态调用这个类中的属性了:
- Assembly assembly = NewAssembly();
- objectClass1 = assembly.CreateInstance("DynamicClass");
- ReflectionSetProperty(Class1,"aaa", 10);
- ReflectionGetProperty(Class1,"aaa");
- objectClass2 = assembly.CreateInstance("DynamicClass");
- ReflectionSetProperty(Class1,"bbb", 20);
- ReflectionGetProperty(Class1,"bbb");
- DynamicClass是我动态类的类名,aaa和bbb是其中的属性
- ReflectionSetProperty和ReflectionGetProperty代码如下:
- 给属性赋值
- privatestaticvoidReflectionSetProperty(objectobjClass,stringpropertyName,intvalue)
- {
- PropertyInfo[] infos = objClass.GetType().GetProperties();
- foreach(PropertyInfo infoininfos)
- {
- if(info.Name == propertyName && info.CanWrite)
- {
- info.SetValue(objClass, value,null);
- }
- }
- }
- 取得属性的值
- privatestaticvoidReflectionGetProperty(objectobjClass,stringpropertyName)
- {
- PropertyInfo[] infos = objClass.GetType().GetProperties();
- foreach(PropertyInfo infoininfos)
- {
- if(info.Name == propertyName && info.CanRead)
- {
- System.Console.WriteLine(info.GetValue(objClass,null));
- }
- }
- }
C#代码
- <SPAN id=comment_body_1095076class=blog_comment_body>属性的赋值应该可以这样写:
- 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);
- }
- </SPAN>
/* * 使用C#动态编译代码和执行 * 作者: yaob */ static void Main(string[] args) { //编译器 CodeDomProvider cdp = CodeDomProvider.CreateProvider("C#"); //编译器的参数 CompilerParameters cp = new CompilerParameters(); cp.ReferencedAssemblies.Add("System.dll"); cp.GenerateExecutable = false; cp.GenerateInMemory = true; //编译结果 CompilerResults cr = cdp.CompileAssemblyFromSource(cp, HelloWorld()); if (cr.Errors.HasErrors) Console.WriteLine("编译出错!"); else { //编译后的程序集 Assembly ass = cr.CompiledAssembly; // 得到HelloWorld类中的SayHello方法 Type type = ass.GetType("HelloWorld.HelloWorld"); MethodInfo mi = type.GetMethod("SayHello"); // 执行 mi.Invoke(null, null); } } //动态构建的代码 static string HelloWorld() { StringBuilder sbCode = new StringBuilder(); sbCode.AppendLine("using System;"); sbCode.AppendLine("namespace HelloWorld"); sbCode.AppendLine("{"); sbCode.AppendLine(" class HelloWorld"); sbCode.AppendLine(" {"); sbCode.AppendLine(" public static void SayHello()"); sbCode.AppendLine(" {"); sbCode.AppendLine(" Console.WriteLine(\"Hello~ World~!\");"); sbCode.AppendLine(" }"); sbCode.AppendLine(" }"); sbCode.AppendLine("}"); return sbCode.ToString(); } |