動態代碼的使用(反射和動態生成類)(轉載)

 在軟件開發尤其是框架和底層開發時,爲了更靈活的控制代碼,常常需要進行一些動態的操作。比如根據用戶的輸入等動態的調用類中的方法或者根據數據庫表結 構、用戶要求動態的生成一些類,然後再動態的調用類中的方法。當然使用這些方式時會對性能有一點影響,具體使用過程中可以根據實際情況來定,不過一般的 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 });
                } [Page]
            }

            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; [Page]

            
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) [Page]
                {
                    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));
                }
            }
        }
發佈了4 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章