C#动态编程

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Test();
 6         }
 7 
 8         public static void Test()
 9         {
10             //声明代码的部分
11             CodeCompileUnit compunit = new CodeCompileUnit();
12             CodeNamespace sample = new CodeNamespace("命名空间");
13             compunit.Namespaces.Add(sample);
14 
15             //引用命名空间
16             sample.Imports.Add(new CodeNamespaceImport("System"));//导入System命名空间
17             sample.Imports.Add(new CodeNamespaceImport("System.Linq"));//导入System.Linq命名空间
18 
19             //在命名空间下添加一个类
20             CodeTypeDeclaration wrapProxyClass = new CodeTypeDeclaration("类名");
21             //wrapProxyClass.BaseTypes.Add(baseType);// 如果需要的话 在这里声明继承关系 (基类 , 接口)
22             wrapProxyClass.CustomAttributes.Add(new CodeAttributeDeclaration("Serializable"));//添加一个Attribute到class上
23             sample.Types.Add(wrapProxyClass);//把这个类添加到命名空间 ,待会儿才会编译这个类
24 
25             //为这个类添加一个无参构造函数  其实不添加也没事的, 只是做个demo而已
26             CodeConstructor constructor = new CodeConstructor();
27             constructor.Attributes = MemberAttributes.Public;
28             wrapProxyClass.Members.Add(constructor);
29             
30             //为这个类添加一个方法   public override int 方法名(string str);
31             System.CodeDom.CodeMemberMethod method = new CodeMemberMethod();
32             method.Name = "方法名";
33             method.Attributes = MemberAttributes.Public;//声明方法是公开 并且override的
34             method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "str")); //这个方法添加一个输入参数
35             method.ReturnType = new CodeTypeReference(typeof(int));//声明返回值的类型
36             method.Statements.Add(new CodeSnippetStatement(@" 
37                 Console.WriteLine(str);
38                 return 1; ")); //方法体里面很简单 直接返回 一个1;
39             wrapProxyClass.Members.Add(method);
40 
41             CSharpCodeProvider cprovider = new CSharpCodeProvider();
42 
43             ICodeGenerator gen = cprovider.CreateGenerator();
44             StringBuilder fileContent = new StringBuilder();
45             using (StringWriter sw = new StringWriter(fileContent))
46             {
47                 gen.GenerateCodeFromCompileUnit(compunit, sw, new CodeGeneratorOptions());//想把生成的代码保存为cs文件
48             }
49 
50             ICodeCompiler compiler = cprovider.CreateCompiler();
51 
52             //编译参数
53             CompilerParameters cp = new CompilerParameters();
54             cp.ReferencedAssemblies.Add("System.dll");//刚才引用了命名空间 这里是添加引用
55             cp.ReferencedAssemblies.Add("System.Core.dll");//刚才引用了命名空间 这里是添加引用
56 
57             cp.OutputAssembly = "输出dll的位置.dll";
58             cp.GenerateInMemory = false; //是否只在内存中生成
59             cp.IncludeDebugInformation = true;//包含调试符号  pdb文件
60             cp.GenerateExecutable = false;//生成dll,不是exe 
61             cp.WarningLevel = 4;
62             cp.TreatWarningsAsErrors = false;
63 
64             string filePath = "生成cs文件的保存位置.cs";
65             File.WriteAllText(filePath, fileContent.ToString());
66             CompilerResults cr = compiler.CompileAssemblyFromFile(cp, filePath); //保存文件再进行编译 待会儿调试就比较方便了 ,可以直接断点到刚才生成的文件里面
67             //  CompilerResults cr = compiler.CompileAssemblyFromDom(cp, compunit); //这样的生成 不用写文件 ,就是调试麻烦
68             String outputMessage = "";
69             foreach (var item in cr.Output)
70             {
71                 outputMessage += item + Environment.NewLine;//调试的最终输出信息
72             }
73             if (cr.Errors.Count > 0)//有编译错误就抛出异常
74             {
75                 throw new Exception("error:" + Environment.NewLine + outputMessage);
76             }
77 
78             string dllDir = Path.Combine(Directory.GetCurrentDirectory(), cp.OutputAssembly);
79             Console.WriteLine(dllDir);
80 
81             Assembly ass = Assembly.LoadFile(dllDir);
82             Type t = ass.GetType("命名空间.类名");
83             var obj = ass.CreateInstance("命名空间.类名");
84             MethodInfo mi = t.GetMethod("方法名");
85             mi.Invoke(obj, new object[] { "Hello _ World!" });
86         }
87     }

 

posted on 2017-01-16 14:46  夏雨微尘  阅读(150)  评论(0)    收藏  举报

导航