動態代碼的使用(反射和動態產生類)

來源:互聯網
上載者:User

動態代碼的使用(反射和動態產生類)
    在軟體開發尤其是架構和底層開發時,為了更靈活的控制碼,常常需要進行一些動態操作。比如根

據使用者的輸入等動態調用類中的方法或者根據資料庫表結 構、使用者要求動態產生一些類,然後再動態

的調用類中的方法。當然使用這些方式時會對效能有一點影響,具體使用過程中可以根據實際情況來定,不

過一般的 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));
                }
            }
        }

 

 

添加自訂的dll和命名空間,注意要絕對路徑(系統本身的不用,不過codedom的版本要對上,比如2005的codedom加linq的dll還是要絕對路徑),至於怎麼取絕對路徑,自己來吧

        CodeCompileUnit m_CodeCompileUnit = new CodeCompileUnit();
        CodeNamespace m_CodeNameSpace = new CodeNamespace("xml.tables");

        m_CodeCompileUnit.ReferencedAssemblies.Add(@"E:\本地測試\動態產生代碼\動態產生代碼\Bin\RDll.dll");
        m_CodeNameSpace.Imports.Add(new System.CodeDom.CodeNamespaceImport("RDll"));

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.