C#强化系列文章五:动态代码的使用(反射和动态生成类)
生活随笔
收集整理的這篇文章主要介紹了
C#强化系列文章五:动态代码的使用(反射和动态生成类)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
在軟件開(kāi)發(fā)尤其是框架和底層開(kāi)發(fā)時(shí),為了更靈活的控制代碼,常常需要進(jìn)行一些動(dòng)態(tài)的操作。比如根據(jù)用戶的輸入等動(dòng)態(tài)的調(diào)用類中的方法或者根據(jù)數(shù)據(jù)庫(kù)表結(jié)構(gòu)、用戶要求動(dòng)態(tài)的生成一些類,然后再動(dòng)態(tài)的調(diào)用類中的方法。當(dāng)然使用這些方式時(shí)會(huì)對(duì)性能有一點(diǎn)影響,具體使用過(guò)程中可以根據(jù)實(shí)際情況來(lái)定,不過(guò)一般的B/S開(kāi)發(fā)中主要的瓶頸還是在數(shù)據(jù)庫(kù)操作和網(wǎng)速方面,這點(diǎn)影響應(yīng)該可以忽略的
下面我就從這兩個(gè)方面來(lái)說(shuō)說(shuō)動(dòng)態(tài)代碼的使用:
一、反射的使用
可以使用反射動(dòng)態(tài)地創(chuàng)建類型的實(shí)例,將類型綁定到現(xiàn)有對(duì)象,或從現(xiàn)有對(duì)象中獲取類型。然后,可以調(diào)用類型的方法或訪問(wèn)其字段和屬性。
需要使用的命名空間:System.Reflection
反射的作用很多,下面的例子主要是看一下怎么動(dòng)態(tài)的調(diào)用類中的方法。
例子類
????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);
????????}
????}
這個(gè)例子中提供了三個(gè)方法和一個(gè)屬性,下面的代碼來(lái)動(dòng)態(tài)的調(diào)用它們:
????????????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用來(lái)設(shè)置要取得哪些類型的方法,然后我們就可以取得這些方法來(lái)動(dòng)態(tài)的調(diào)用。(當(dāng)然為了可以循環(huán)的調(diào)用方法,在方法的命名方面可以自己指定一個(gè)規(guī)則)
二、動(dòng)態(tài)生成類
我們可以在程序運(yùn)行過(guò)程中調(diào)用.NET中提供的編譯類,動(dòng)態(tài)的將一段string編譯成一個(gè)類,然后再通過(guò)反射來(lái)調(diào)用它
需要使用的命名空間:System.CodeDom System.CodeDom.Compiler Microsoft.CSharp System.Reflection
動(dòng)態(tài)創(chuàng)建、編譯類的代碼如下:
????????public?static?Assembly?NewAssembly()
????????{
????????????//創(chuàng)建編譯器實(shí)例。???
????????????provider?=?new?CSharpCodeProvider();
????????????//設(shè)置編譯參數(shù)。???
????????????paras?=?new?CompilerParameters();
????????????paras.GenerateExecutable?=?false;
????????????paras.GenerateInMemory?=?true;
????????????//創(chuàng)建動(dòng)態(tài)代碼。???
????????????StringBuilder?classSource?=?new?StringBuilder();
????????????classSource.Append("public???class???DynamicClass?\n");
????????????classSource.Append("{\n");
????????????//創(chuàng)建屬性。???
????????????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方法就是用來(lái)拼寫字符串的
整個(gè)代碼比較簡(jiǎn)單,主要步驟就是:1、拼寫類的字符串? 2、調(diào)用CSharpCodeProvider類進(jìn)行編譯得到程序集(assembly)
接下來(lái)就可以利用之前反射的方法來(lái)動(dòng)態(tài)調(diào)用這個(gè)類中的屬性了:
????????????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是我動(dòng)態(tài)類的類名,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));
????????????????}
????????????}
????????}
下面我就從這兩個(gè)方面來(lái)說(shuō)說(shuō)動(dòng)態(tài)代碼的使用:
一、反射的使用
可以使用反射動(dòng)態(tài)地創(chuàng)建類型的實(shí)例,將類型綁定到現(xiàn)有對(duì)象,或從現(xiàn)有對(duì)象中獲取類型。然后,可以調(diào)用類型的方法或訪問(wèn)其字段和屬性。
需要使用的命名空間:System.Reflection
反射的作用很多,下面的例子主要是看一下怎么動(dòng)態(tài)的調(diào)用類中的方法。
例子類
????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);
????????}
????}
這個(gè)例子中提供了三個(gè)方法和一個(gè)屬性,下面的代碼來(lái)動(dòng)態(tài)的調(diào)用它們:
????????????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用來(lái)設(shè)置要取得哪些類型的方法,然后我們就可以取得這些方法來(lái)動(dòng)態(tài)的調(diào)用。(當(dāng)然為了可以循環(huán)的調(diào)用方法,在方法的命名方面可以自己指定一個(gè)規(guī)則)
二、動(dòng)態(tài)生成類
我們可以在程序運(yùn)行過(guò)程中調(diào)用.NET中提供的編譯類,動(dòng)態(tài)的將一段string編譯成一個(gè)類,然后再通過(guò)反射來(lái)調(diào)用它
需要使用的命名空間:System.CodeDom System.CodeDom.Compiler Microsoft.CSharp System.Reflection
動(dòng)態(tài)創(chuàng)建、編譯類的代碼如下:
????????public?static?Assembly?NewAssembly()
????????{
????????????//創(chuàng)建編譯器實(shí)例。???
????????????provider?=?new?CSharpCodeProvider();
????????????//設(shè)置編譯參數(shù)。???
????????????paras?=?new?CompilerParameters();
????????????paras.GenerateExecutable?=?false;
????????????paras.GenerateInMemory?=?true;
????????????//創(chuàng)建動(dòng)態(tài)代碼。???
????????????StringBuilder?classSource?=?new?StringBuilder();
????????????classSource.Append("public???class???DynamicClass?\n");
????????????classSource.Append("{\n");
????????????//創(chuàng)建屬性。???
????????????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方法就是用來(lái)拼寫字符串的
整個(gè)代碼比較簡(jiǎn)單,主要步驟就是:1、拼寫類的字符串? 2、調(diào)用CSharpCodeProvider類進(jìn)行編譯得到程序集(assembly)
接下來(lái)就可以利用之前反射的方法來(lái)動(dòng)態(tài)調(diào)用這個(gè)類中的屬性了:
????????????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是我動(dòng)態(tài)類的類名,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));
????????????????}
????????????}
????????}
總結(jié)
以上是生活随笔為你收集整理的C#强化系列文章五:动态代码的使用(反射和动态生成类)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 职业生涯规划与管理
- 下一篇: 一步一步学Silverlight 2系列