使用反射和codeDom實現C#插件開發(3)主程序開發之動態類

接着上一篇的講,如何在主程序中調用插件。
1.新建項目,命名爲0331使用動態類和反射設置某個類中的變量值(好變態的中文項目名!)
2.添加引用,將someInterface和標記屬性添加進來。
3.添加一個類,名爲dynamic.cs;該類即爲實現動態類生成的類。
主要包含三個功能,一是動態的編寫出來代碼,二是編寫編譯選項;三是執行編譯,生成類庫。代碼不做詳細介紹了,自己去補codeDOM相關知識。


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
using Microsoft.CSharp;
using System.Collections;




namespace _0331使用動態類和反射設置某個類中的變量值
{
//忘了爲什麼使用靜態類了,沒測試其他的行不行
    public static class dynamic
    {
        //生成類的代碼
        public static CompilerResults compileCode(string sourceCSFile,string dllName)
        {


            CSharpCodeProvider compiler = new CSharpCodeProvider(
                new Dictionary<string, string>() { { "CompilerVersion", "v3.5" } });


            CompilerParameters cp = new CompilerParameters();
            cp.ReferencedAssemblies.Add("System.dll");
            cp.ReferencedAssemblies.Add("System.Data.dll");
            cp.ReferencedAssemblies.Add(dllName);
            cp.ReferencedAssemblies.Add("someInterface.dll");
            cp.OutputAssembly = "dynamic.dll";
            cp.GenerateExecutable = false;


            CompilerResults cr = compiler.CompileAssemblyFromFile(cp, sourceCSFile);


            return cr;


        }  


        //生成類的代碼,帶參數
        private static CodeCompileUnit CompileUnit(string fullClassName, ArrayList fields)
        {


            CodeCompileUnit compunit = new CodeCompileUnit();
            CodeNamespace sample = new CodeNamespace("dynamicNS");
            CodeTypeDeclaration myclass = new CodeTypeDeclaration("dynamicClass");


            #region 設置變量值的函數
            CodeMemberMethod setValues = new CodeMemberMethod();
            setValues.Name = "setValues";
            setValues.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            CodeParameterDeclarationExpression cp2 = new CodeParameterDeclarationExpression("System.Object", "obj");
            setValues.Parameters.Add(cp2);


            CodeVariableDeclarationStatement cv2 = DeclareVariables(fullClassName, "dllClass");
            setValues.Statements.Add(cv2);


            CodeTypeReference ct = new CodeTypeReference(fullClassName);


            CodeAssignStatement dllclass = new CodeAssignStatement(new CodeVariableReferenceExpression("dllClass"), new CodeCastExpression(fullClassName, new CodeVariableReferenceExpression("obj")));


            setValues.Statements.Add(dllclass);


            for (int i = 0; i < fields.Count; i = i + 3)
            {
                string name = "dllClass." + fields[i].ToString();
                if (fields[i + 2].ToString().IndexOf(',') == -1)
                {
                    CodeAssignStatement param = new CodeAssignStatement(new CodeVariableReferenceExpression(name), new CodePrimitiveExpression(fields[i + 2]));
                    setValues.Statements.Add(param);
                }
                else
                {
                    string[] temp = fields[i + 2].ToString().Split(',');
                    int len = temp.Length;
                    if (fields[i + 1].ToString() == "Int32[]")
                    {
                        for (int j = 0; j < len; j++)
                        {
                            // Create an array indexer expression that references index 5 of array "x"
                            CodeArrayIndexerExpression ci1 = new CodeArrayIndexerExpression(new CodeVariableReferenceExpression(name), new CodePrimitiveExpression(j));
                            // Assigns the value of the 10 to the integer variable "i".
                            CodeAssignStatement as1 = new CodeAssignStatement(ci1, new CodePrimitiveExpression(Convert.ToInt32(temp[j].Trim())));
                            setValues.Statements.Add(as1);
                        }
                    }
                    else if (fields[i + 1].ToString() == "String[]")
                    {
                        for (int j = 0; j < len; j++)
                        {
                            CodeArrayIndexerExpression ci1 = new CodeArrayIndexerExpression(new CodeVariableReferenceExpression(name), new CodePrimitiveExpression(j));
                            CodeAssignStatement as1 = new CodeAssignStatement(ci1, new CodePrimitiveExpression(temp[j].Trim()));
                            setValues.Statements.Add(as1);
                        }
                    }
                    else
                    {
                    }
                }
            }
            #endregion


            compunit.Namespaces.Add(sample);
            sample.Imports.Add(new CodeNamespaceImport("System"));
            sample.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
            sample.Imports.Add(new CodeNamespaceImport("System.ComponentModel"));
            sample.Imports.Add(new CodeNamespaceImport("System.Data")); ;
            sample.Imports.Add(new CodeNamespaceImport("System.Text"));


            sample.Types.Add(myclass);
            myclass.Members.Add(setValues);
            return compunit;
        }


        public static void generateCode(string filenm, string fullclassname, ArrayList fields)
        {
            CSharpCodeProvider gen = new CSharpCodeProvider();
            StreamWriter sw = new StreamWriter(filenm, false);


            gen.GenerateCodeFromCompileUnit(CompileUnit(fullclassname, fields), sw, new CodeGeneratorOptions());
            sw.Close();
        }


      //在網上找的的函數,解決了聲明變量的問題.
        private static CodeVariableDeclarationStatement DeclareVariables(string dataType, string Name)
        {
            // 爲將要創建的變量類型創建一個CodeTypeReference對象, 
            // 這使得我們不必去關注該類數據在特定語言環境中的 
            // 與數據類型有關的細節問題。 
            CodeTypeReference tr = new CodeTypeReference(dataType);
            // CodeVariableDeclarationStatement對象使得我們不必糾纏於 
            // 與特定語言有關的下列細節:在該語言的變量聲明語句中, 
            // 應該是數據類型在前,還是變量名稱在前;聲明變量時是 
            // 否要用到Dim之類的關鍵詞. 
            CodeVariableDeclarationStatement Declaration =
            new CodeVariableDeclarationStatement(tr, Name);
            // CodeObjectCreateExpression負責處理所有調用構造器的細節。 
            // 大多數情況下應該是new,但有時要使用New。但不管怎樣, 
            // 我們不必去關注這些由語言類型決定的細節. 
            CodeObjectCreateExpression newStatement = new
            CodeObjectCreateExpression();
            // 指定我們要調用其構造器的對象. 
            newStatement.CreateType = tr;
            // 變量將通過調用其構造器的方式初始化. 
            Declaration.InitExpression = newStatement;
            return Declaration;
        }
    }
}


4.再寫一個類來保存提取出來的參數;


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace _0331使用動態類和反射設置某個類中的變量值
{
    public class programData
    {
        string paramName;
        string paramType;
        string paramValue;
        string paramMSG;
        public string 參數名稱
        {
            set;
            get;
        }


        public string 參數類型
        {
            set;
            get;
        }


        public string 參數值
        {
            set;
            get;
        }


        public string 參數描述
        {
            set;
            get;
        }
    }


    
}




準備工作基本都完成了,下面開始寫主程序了。
發佈了36 篇原創文章 · 獲贊 8 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章