C#强化系列文章五:动态代码的使用(反射和动态生成类)
生活随笔
收集整理的這篇文章主要介紹了
C#强化系列文章五:动态代码的使用(反射和动态生成类)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在軟件開發尤其是框架和底層開發時,為了更靈活的控制代碼,常常需要進行一些動態的操作。比如根據用戶的輸入等動態的調用類中的方法或者根據數據庫表結構、用戶要求動態的生成一些類,然后再動態的調用類中的方法。當然使用這些方式時會對性能有一點影響,具體使用過程中可以根據實際情況來定,不過一般的B/S開發中主要的瓶頸還是在數據庫操作和網速方面,這點影響應該可以忽略的
下面我就從這兩個方面來說說動態代碼的使用:
一、反射的使用
可以使用反射動態地創建類型的實例,將類型綁定到現有對象,或從現有對象中獲取類型。然后,可以調用類型的方法或訪問其字段和屬性。
需要使用的命名空間: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));
????????????????}
????????????}
????????}
下面我就從這兩個方面來說說動態代碼的使用:
一、反射的使用
可以使用反射動態地創建類型的實例,將類型綁定到現有對象,或從現有對象中獲取類型。然后,可以調用類型的方法或訪問其字段和屬性。
需要使用的命名空間: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));
????????????????}
????????????}
????????}
總結
以上是生活随笔為你收集整理的C#强化系列文章五:动态代码的使用(反射和动态生成类)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 职业生涯规划与管理
- 下一篇: C# 之不安全代码(2)