使用反射和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;
        }
    }


    
}




准备工作基本都完成了,下面开始写主程序了。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技道两进

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值