微软CodeDom模型学习笔记(五)

5,GenerateCodeFromType 这个版本实际上是GenerateCodeFromMemberd的一个阉割版本,在GenerateCodeFromMember版本的最后一部份已经详细研究了,不再继续研究 6, GenerateCodeFromCompileUnit为指定的代码文档对象模型 (CodeDOM) 编译单元生成代码,并使用指定的选项将代码发送到指定的文本编写器。 CodeCompileUnit ret = new CodeCompileUnit(); codeProvider. GenerateCodeFromCompileUnit(ret, tw, options); 输出的代码字符串为: //------------------------------------------------------------------------------ // // 此代码由工具生成。 // 运行库版本:2.0.50727.3603 // // 对此文件的更改可能会导致不正确的行为,并且如果 // 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ 输出的是默认的模版标题 a, AssemblyCustomAttributes获取生成的程序集的自定义属性集合。 CodeCompileUnit ret = new CodeCompileUnit(); CodeTypeReference ct = new CodeTypeReference(typeof(System.Data.DataTable)); CodeAttributeDeclaration attr = new CodeAttributeDeclaration(ct); ret.AssemblyCustomAttributes.Add(attr); codeProvider. GenerateCodeFromCompileUnit(ret, tw, options); 输出的代码字符串为: //------------------------------------------------------------------------------ // // 此代码由工具生成。 // 运行库版本:2.0.50727.3603 // // 对此文件的更改可能会导致不正确的行为,并且如果 // 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ [assembly: System.Data.DataTable()] b, CodeNamespace获取命名空间的集合。 CodeCompileUnit ret = new CodeCompileUnit(); CodeTypeReference ct = new CodeTypeReference(typeof(System.Data.DataTable)); CodeAttributeDeclaration attr = new CodeAttributeDeclaration(ct); ret.AssemblyCustomAttributes.Add(attr); CodeNamespace ns = new CodeNamespace("MyNameSpace"); ret.Namespaces.Add(new CodeNamespace(ns)); codeProvider. GenerateCodeFromCompileUnit(ret, tw, options); 输出的代码字符串为: //------------------------------------------------------------------------------ // // 此代码由工具生成。 // 运行库版本:2.0.50727.3603 // // 对此文件的更改可能会导致不正确的行为,并且如果 // 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ [assembly: System.Data.DataTable()] namespace MyNameSpace { } c, ReferencedAssemblies获取引用的程序集。从生成的源代码上看不出任何效果,估计在编译的时候才起作用,那就编译时在研究了 d, StartDirectives获取包含开始指令的 CodeDirectiveCollection 对象。不明白意思,那就试验研究吧,从CodeDom命名空间下看, System.CodeDom.CodeDirective System.CodeDom.CodeChecksumPragma System.CodeDom.CodeRegionDirective 有两个子类,先研究简单的CodeRegionDirective,从字面上看与#region有关,就从它下手了 d-1 ,CodeRegionDirective CodeCompileUnit ret = new CodeCompileUnit(); CodeRegionDirective dc=new CodeRegionDirective (); dc.RegionText ="这里是一个Region!"; dc.RegionMode = CodeRegionMode.Start; ret.StartDirectives.Add(dc); codeProvider. GenerateCodeFromCompileUnit (ret, tw, options); 输出的代码字符串为: #region 这里是一个Region! //------------------------------------------------------------------------------ // // 此代码由工具生成。 // 运行库版本:2.0.50727.3603 // // 对此文件的更改可能会导致不正确的行为,并且如果 // 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ 将RegionMode换成end看看 CodeCompileUnit ret = new CodeCompileUnit(); CodeRegionDirective dc=new CodeRegionDirective (); dc.RegionText ="这里是一个Region!"; dc.RegionMode = CodeRegionMode.End; ret.StartDirectives.Add(dc); codeProvider.GenerateCodeFromCompileUnit (ret, tw, options); 输出的代码字符串为: #endregion //---------------------------------------------------------------------------- // // 此代码由工具生成。 // 运行库版本:2.0.50727.3603 // // 对此文件的更改可能会导致不正确的行为,并且如果 // 重新生成代码,这些更改将会丢失。 // //---------------------------------------------------------------------------- 换成None呢? CodeCompileUnit ret = new CodeCompileUnit(); CodeRegionDirective dc=new CodeRegionDirective (); dc.RegionText ="这里是一个Region!"; dc.RegionMode = CodeRegionMode.None; ret.StartDirectives.Add(dc); codeProvider.GenerateCodeFromCompileUnit (ret, tw, options); 输出的代码字符串为: //------------------------------------------------------------------- // // 此代码由工具生成。 // 运行库版本:2.0.50727.3603 // // 对此文件的更改可能会导致不正确的行为,并且如果 // 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------- 哦,原来如此!CodeRegionDirective就是这个意思那么搭配EndDirectives一起使用呢 CodeCompileUnit ret = new CodeCompileUnit(); CodeRegionDirective dc=new CodeRegionDirective (); dc.RegionText ="这里是一个Region!"; dc.RegionMode = CodeRegionMode.Start; ret.StartDirectives.Add(dc); dc=new CodeRegionDirective (); dc.RegionMode =CodeRegionMode .End; ret.EndDirectives.Add(dc); codeProvider.GenerateCodeFromCompileUnit (ret, tw, options); 输出的代码字符串为: #region 这里是一个Region! //-------------------------------------------------------- // // 此代码由工具生成。 // 运行库版本:2.0.50727.3603 // // 对此文件的更改可能会导致不正确的行为,并且如果 // 重新生成代码,这些更改将会丢失。 // //-------------------------------------------------------- #endregion 这应该就是CodeRegionDirective的用法了 d-2, CodeChecksumPragma表示代码校验和杂注代码实体。 MSDN也太抽象了吧 CodeCompileUnit ret = new CodeCompileUnit(); CodeChecksumPragma dc = new CodeChecksumPragma(); ret.StartDirectives.Add(dc); codeProvider.GenerateCodeFromCompileUnit (ret, tw, options); 输出的代码字符串为: #pragma checksum "" "{00000000-0000-0000-0000-000000000000}" "" //----------------------------------------------------------------------- // // 此代码由工具生成。 // 运行库版本:2.0.50727.3603 // // 对此文件的更改可能会导致不正确的行为,并且如果 // 重新生成代码,这些更改将会丢失。 // //----------------------------------------------------------------------- 什么意思?把属性设置上看看 CodeCompileUnit ret = new CodeCompileUnit(); CodeChecksumPragma dc = new CodeChecksumPragma(); dc.FileName = "aa.txt"; dc.ChecksumAlgorithmId = Guid.NewGuid(); dc.ChecksumData = new byte[] { 1, 2, 3, 4,5,6,7 }; ret.StartDirectives.Add(dc); codeProvider.GenerateCodeFromCompileUnit (ret, tw, options); 输出的代码字符串为: #pragma checksum "aa.txt" "{0e627ca7-f0da-42fe-b359-e7c21ca4cb9a}" "010203040506 07" //------------------------------------------------------------------------------ // // 此代码由工具生成。 // 运行库版本:2.0.50727.3603 // // 对此文件的更改可能会导致不正确的行为,并且如果 // 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ 还是不懂,对C#的宏意思很清楚了请告诉我下,谢谢 QQ:32354456 Email:diablohe@hotmail.com 该总结下了,关于代码生成的相关内容[GenerateCode***]大概就这么多了,如有遗漏,请告知下,我再学习!以上所有的学习都是针对C#语言,当然可以针对各种语言,只需要使用对应得CodeDomProvider就可以了。学了这么多,感觉这个模型还是很有用的,以后可以把这个功能集成到自己的程序里,根据业务逻辑生成CodeDom模型的框架,生成代码文件,然后可以修改代码文件,编译到自己的程序集合里,为用户提供强大而方便的插件功能,应该还是很爽阿!实战一下吧!我希望自动生成一个代码框架如下(事先一个观察者模式的代码框架吧),目标如下: namespace CodeDomPrj { using System; using System.Collections.Generic; using System.Linq; using System.Text; // 被观察者的实体对象 public class Subject { private String _name; public virtual String Name { get{return _name;} set{ _name = value; if ((NameChanged != null)) { this.NameChanged(this, new NameChangedEventArgs(Name)); } } } public event EventHandler NameChanged; public class NameChangedEventArgs : EventArgs { private String _name; public NameChangedEventArgs(String name) { this._name = name; } public virtual String Name { get{return _name;} } } } // 观察者 public class Observer { private Subject _subject; public Observer(Subject subject) { _subject = subject; Subject.NameChanged += new EventHandler(this.Subject_NameChanged); } public virtual Subject Subject { get{return _subject;} } private void Subject_NameChanged(object sender, Subject.NameChangedEventArgs e) { Console.WriteLine(e.Name); } } } 下面就开始了 //namespace CodeDomPrj CodeNamespace ns = new CodeNamespace("CodeDomPrj"); // using System; // using System.Collections.Generic; // using System.Linq; // using System.Text; CodeRegionDirective importStart = new CodeRegionDirective(); importStart.RegionMode = CodeRegionMode.Start; CodeNamespaceImport import = new CodeNamespaceImport("System"); ns.Imports.Add(import); import = new CodeNamespaceImport("System.Collections.Generic"); ns.Imports.Add(import); import = new CodeNamespaceImport("System.Linq"); ns.Imports.Add(import); import = new CodeNamespaceImport("System.Text"); ns.Imports.Add(import); // // 被观察者的实体对象 // public class Subject CodeTypeDeclaration Subject = new CodeTypeDeclaration(); Subject.Name = "Subject"; Subject.Comments.Add(new CodeCommentStatement("被观察者的实体对象")); Subject.TypeAttributes = System.Reflection.TypeAttributes.Public; { // public class NameChangedEventArgs : EventArgs CodeTypeDeclaration NameChangedEventArgs = new CodeTypeDeclaration(); NameChangedEventArgs.TypeAttributes = System.Reflection.TypeAttributes.Public; NameChangedEventArgs.BaseTypes.Add(new CodeTypeReference("EventArgs")); NameChangedEventArgs.Name = "NameChangedEventArgs"; // private String _name; CodeMemberField _name = new CodeMemberField("String", "_name"); NameChangedEventArgs.Members.Add(_name); // public virtual String Name CodeMemberProperty Name = new CodeMemberProperty(); Name.Name = "Name"; Name.HasGet = true; Name.Attributes = MemberAttributes.Public | MemberAttributes.VTableMask; Name.Type = new CodeTypeReference("String"); // get{return _name;} CodeMethodReturnStatement Return = new CodeMethodReturnStatement(); Return.Expression = new CodeVariableReferenceExpression("_name"); Name.GetStatements.Add(Return); NameChangedEventArgs.Members.Add(Name); // public NameChangedEventArgs(String name) CodeConstructor cst = new CodeConstructor(); cst.Attributes = MemberAttributes.Public; cst.Parameters.Add(new CodeParameterDeclarationExpression("String", "name")); // this._name = name; CodeFieldReferenceExpression left = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "_name"); CodeVariableReferenceExpression right = new CodeVariableReferenceExpression("name"); CodeAssignStatement ass = new CodeAssignStatement(); ass.Left = left; ass.Right = right; cst.Statements.Add(ass); NameChangedEventArgs.Members.Add(cst); Subject.Members.Add(NameChangedEventArgs); } { // private String _name; CodeMemberField _name = new CodeMemberField("String", "_name"); Subject.Members.Add(_name); // public virtual String Name CodeMemberProperty Name = new CodeMemberProperty(); Name.Name = "Name"; Name.HasGet = true; Name.HasSet = true; Name.Attributes = MemberAttributes.Public | MemberAttributes.VTableMask; Name.Type = new CodeTypeReference("String"); // get{return _name;} CodeMethodReturnStatement Return = new CodeMethodReturnStatement(); Return.Expression = new CodeVariableReferenceExpression("_name"); Name.GetStatements.Add(Return); // _name = value; CodeVariableReferenceExpression _nameRef = new CodeVariableReferenceExpression("_name"); CodeVariableReferenceExpression valueRef = new CodeVariableReferenceExpression("value"); CodeAssignStatement assign = new CodeAssignStatement(); assign.Left = _nameRef; assign.Right = valueRef; Name.SetStatements.Add(assign); // if ((NameChanged != null)) CodeConditionStatement ifCon = new CodeConditionStatement(); CodeBinaryOperatorExpression condition = new CodeBinaryOperatorExpression(); condition.Left = new CodeVariableReferenceExpression("NameChanged"); condition.Right = new CodePrimitiveExpression(null); condition.Operator = CodeBinaryOperatorType.IdentityInequality; ifCon.Condition = condition; // this.NameChanged(this, new NameChangedEventArgs(Name)); CodeEventReferenceExpression ev = new CodeEventReferenceExpression(); ev.TargetObject = new CodeThisReferenceExpression(); ev.EventName = "NameChanged"; CodeDelegateInvokeExpression inv = new CodeDelegateInvokeExpression(); inv.TargetObject = ev; inv.Parameters.Add(new CodeThisReferenceExpression()); inv.Parameters.Add(new CodeObjectCreateExpression(new CodeTypeReference("NameChangedEventArgs"), new CodeVariableReferenceExpression("Name"))); ifCon.TrueStatements.Add(inv); // public event EventHandler NameChanged; CodeMemberEvent evn = new CodeMemberEvent(); evn.Attributes = MemberAttributes.Public; evn.Name = "NameChanged"; evn.Type = new CodeTypeReference("EventHandler"); Subject.Members.Add(evn); Name.SetStatements.Add(ifCon); Subject.Members.Add(Name); ns.Types.Add(Subject); } // // 观察者 // public class Observer CodeTypeDeclaration Observer = new CodeTypeDeclaration(); Observer.IsClass = true; Observer.TypeAttributes = System.Reflection.TypeAttributes.Public; Observer.Name = "Observer"; Observer.Comments.Add(new CodeCommentStatement("观察者")); { // private Subject _subject; CodeMemberField _field = new CodeMemberField(); _field.Name = "_subject"; _field.Type = new CodeTypeReference("Subject"); Observer.Members.Add(_field); // public virtual Subject Subject CodeMemberProperty property = new CodeMemberProperty(); property.Name = "Subject"; property.Type = new CodeTypeReference("Subject"); property.Attributes = MemberAttributes.Public | MemberAttributes.VTableMask; property.HasGet = true; // get{return _subject;} CodeMethodReturnStatement returnSub = new CodeMethodReturnStatement(); returnSub.Expression = new CodeVariableReferenceExpression("_subject"); property.GetStatements.Add(returnSub); Observer.Members.Add(property); // public Observer(Subject subject) CodeConstructor cst = new CodeConstructor(); cst.Attributes = MemberAttributes.Public | MemberAttributes.VTableMask; CodeParameterDeclarationExpression arg = new CodeParameterDeclarationExpression(); arg.Type = new CodeTypeReference("Subject"); arg.Name = "subject"; cst.Parameters.Add(arg); // _subject = subject; CodeVariableReferenceExpression left = new CodeVariableReferenceExpression("_subject"); CodeVariableReferenceExpression right = new CodeVariableReferenceExpression("subject"); CodeAssignStatement assign = new CodeAssignStatement(); assign.Left = left; assign.Right = right; cst.Statements.Add(assign); // Subject.NameChanged += new EventHandler(this.Subject_NameChanged); CodeAttachEventStatement attach = new CodeAttachEventStatement(); CodeEventReferenceExpression ev=new CodeEventReferenceExpression (); ev.TargetObject =new CodeVariableReferenceExpression("Subject"); ev.EventName ="NameChanged"; attach.Event = ev; CodeDelegateCreateExpression listen = new CodeDelegateCreateExpression(); listen.MethodName = "Subject_NameChanged"; listen.TargetObject = new CodeThisReferenceExpression(); listen.DelegateType = new CodeTypeReference("EventHandler"); attach.Listener = listen; cst.Statements.Add(attach ); Observer.Members.Add(cst); // private void Subject_NameChanged(object sender, Subject.NameChangedEventArgs e) CodeMemberMethod method = new CodeMemberMethod(); method.Name = "Subject_NameChanged"; CodeParameterDeclarationExpression arg1 = new CodeParameterDeclarationExpression(); arg1.Name = "sender"; arg1 .Type =new CodeTypeReference (typeof (object )); method.Parameters.Add(arg1); CodeParameterDeclarationExpression arg2 = new CodeParameterDeclarationExpression(); arg2.Name = "e"; arg2.Type = new CodeTypeReference("Subject.NameChangedEventArgs"); method.Parameters.Add(arg2); // Console.WriteLine(e.Name); CodeMethodInvokeExpression refM = new CodeMethodInvokeExpression(); refM.Method = new CodeMethodReferenceExpression(); refM.Method.TargetObject = new CodeTypeReferenceExpression("Console"); refM.Method.MethodName = "WriteLine"; CodePropertyReferenceExpression arg3 = new CodePropertyReferenceExpression(); arg3.TargetObject = new CodeVariableReferenceExpression("e"); arg3.PropertyName = "Name"; CodeVariableReferenceExpression aa = new CodeVariableReferenceExpression(); aa.VariableName = "e.Name"; refM.Parameters.Add(aa); method.Statements.Add(refM); Observer.Members.Add(method); } ns.Types.Add(Observer); CodeCompileUnit ret = new CodeCompileUnit(); ret.Namespaces.Add(ns); return ret; } codeProvider.GenerateCodeFromCompileUnit (ret, tw, options); 输出的代码字符串为:结果台长就不累赘了!从生成的结果来看,除了排版有少量的不一致以外,符合预期结果!以上的所有内容综合起来算是Codom模型的一个方面的功能,这个方面代表一个从模型到代码的过程!下面就开始研究CodeDom的另一方面,从代码到模型的过程! 7, Parse方法,将从指定文本流读取的代码编译进 CodeCompileUnit。通俗地理解就是根据代码文件生成CodeDom模型. 假设代码文件内容如下 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CodeDomPrj { class codetext { public int i = 0; public string ss { get; set; } public void aa() { } } } 用下面的代码测试 using (TextReader tr = new StringReader(@"../codetext.cs")) { CodeCompileUnit ccu = codeProvider.Parse(tr); } 得到的却是下面的结果,懊恼,可恶的Microsoft,竟然不提供解析器! 试验了所有的codeProvider,结果都是一样,这绝对是微软故意搞的,怎么办?自己写解析器,这是编译器的功能,以前只写过简单的编译程序,很没有信心,这玩意真的很需要功底,看起来简单,实现起来却问题一大堆!网上搜索了下,有一个开源的.Net的IDE开发环境SharpDeveloper,这里有一个IParser接口,值得学习项目中应用ICSharpCode.NRefactory.dll,位于SharpDeveloper的程序集中,导入两个命名空间 using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.Visitors; using (TextReader tr = new StreamReader(@"../../codetext.cs")) { IParser parser=ParserFactory.CreateParser(SupportedLanguage.CSharp, tr); parser.Parse(); CodeDomVisitor vis = new CodeDomVisitor(); vis.VisitCompilationUnit(parser.CompilationUnit, null); CodeCompileUnit ccu= vis.codeCompileUnit; } 观察ccu里面的内容,正是所需要的结构!感谢无私奉献的老外,鄙视某些当宝贝卖钱的!不知道在自己的程序里使用这个程序集是否涉及到版权问题!以上是CodeDom的另一方面,微软并没有提供这方面的功能,使用上面内容的请注意版权问题。再次感谢这些默默无闻无私奉献的老外!下面研究CodeDom的最后一个方面,就是编译 8,CompileAssemblyFromSource从包含源代码的字符串的指定数组,使用指定的编译器设置编译程序集。 options 类型:System.CodeDom.Compiler.CompilerParameters 一个 CompilerParameters 对象,它指示此编译的编译器设置。 sources 类型:System.String[],要编译的源代码字符串的数组。 首先看编译参数设置的问题,这一点MSDN上说的很明白,直接引用过来看看就明白了 CompilerParameters表示用于调用编译器的参数。 MSDN详细描述(整理后):表示 ICodeCompiler 接口的设置和选项的 CompilerParameters 对象。 1,GenerateEcecutable 正在编译可执行程序,则必须将 GenerateExecutable 属性设置为 true。当 GenerateExecutable 设置为 false 时,编译器将生成一个类库。默认情况下,初始化新的 CompilerParameters 时,它的 GenerateExecutable 属性被设置为 false。 2,CodeEntryPointMethod 要从 CodeDOM 图形编译可执行文件,则必须在该图形中定义 CodeEntryPointMethod。如果有多个代码入口点,则可以通过如下方法指示定义要使用的入口点的类:将 MainClass 属性设置为该类的名称。 3,OutputAssembly 在 OutputAssembly 属性中指定输出程序集的文件名。如果不指定,则使用默认的输出文件名。要在生成的程序集中包括调试信息,请将 IncludeDebugInformation 属性设置为 true。 4,ReferenedAssemblies 项目引用了任何程序集,则必须将引用的程序集名称指定为 StringCollection 中的项,设置到在调用编译时使用的 CompilerParameters 的 ReferencedAssemblies 属性中。 5,GenerateInMemory 通过将 GenerateInMemory 属性设置为 true,可以编译写入内存而不是磁盘中的程序集。当在内存中生成程序集时,代码可从 CompilerResults 的 CompiledAssembly 属性中获取生成的程序集的引用。如果程序集被写入到磁盘中,则可以从 CompilerResults 的 PathToAssembly 属性获取到生成的程序集的路径。 6,WarningLevel 要指定暂停编译的警告级别,请将 WarningLevel 属性设置为一个用来表示暂停编译的警告级别的整数。也可以通过将 TreatWarningsAsErrors 属性设置为 true,将编译器配置成在遇到警告时暂停编译。 7,CompilerOptions 要指定调用编译进程时使用的自定义命令行参数字符串,请在 CompilerOptions 属性中设置该字符串。 8,UserToken 如果在调用编译器进程时需要 Win32 安全标记,请在 UserToken 属性中指定该标记。 9,EmbeddedResources 若要将 .NET Framework 资源文件包含到已编译的程序集中,请将这些资源文件的名称添加到 EmbeddedResources 属性中。 10,LinkedResources 若要引用另一程序集中的 .NET Framework 资源,请将这些资源文件的名称添加到 LinkedResources 属性中。 11,Win32Resource 若要将一个 Win32 资源文件包含到已编译的程序集中,请在 Win32Resource 属性中指定该 Win32 资源文件的名称。 下面的代码片段就作为测试代码 namespace simpleapp { using System; using System.Data; class Program { static void Main(string[] args) { DataTable dt = new DataTable("testTable"); Console.WriteLine("Hello world One!"); } } class Program2 { static void Main(string[] args) { Console.WriteLine("Hello world Two!"); } } } CompileAssemblyFromFile从包含在指定文件中的源代码,使用指定的编译器设置编译程序集。 CompilerParameters cp = new CompilerParameters(); cp.GenerateExecutable = true; cp.OutputAssembly = "aa.exe"; cp.IncludeDebugInformation = true; cp.ReferencedAssemblies.Add("System.dll"); cp.ReferencedAssemblies.Add("System.Data.dll"); cp.ReferencedAssemblies.Add("System.Xml.dll"); cp.GenerateInMemory = false; cp.WarningLevel = 3; cp.TreatWarningsAsErrors = false; cp.CompilerOptions = "/optimize"; cp.MainClass = "simpleapp.Program"; CompilerResults ret = codeProvider.CompileAssemblyFromFile(cp, new string []{@"D:/何国栋/工作流学习/simpleapp/simpleapp/Program.cs"}); 测试结果:正确生成了aa.exe 运行aa.exe看看 哈哈,第一个编译顺利成功! CompileAssemblyFromDom基于包含在 CodeCompileUnit 对象的指定数组中的 System.CodeDom 树,使用指定的编译器设置编译程序集。 CompilerParameters cp = new CompilerParameters(); cp.GenerateExecutable = true; cp.OutputAssembly = "aa.exe"; cp.IncludeDebugInformation = true; cp.ReferencedAssemblies.Add("System.dll"); cp.ReferencedAssemblies.Add("System.Data.dll"); cp.ReferencedAssemblies.Add("System.Xml.dll"); cp.GenerateInMemory = false; cp.WarningLevel = 3; cp.TreatWarningsAsErrors = false; cp.CompilerOptions = "/optimize"; cp.MainClass = "simpleapp.Program"; CodeCompileUnit ccu = null; using (TextReader tr = new StreamReader(@"D:/何国栋/工作流学习/simpleapp/simpleapp/Program.cs")) { IParser parser = ParserFactory.CreateParser(SupportedLanguage.CSharp, tr); parser.Parse(); CodeDomVisitor vis = new CodeDomVisitor(); vis.VisitCompilationUnit(parser.CompilationUnit, null); ccu = vis.codeCompileUnit; } CompilerResults ret = codeProvider.CompileAssemblyFromDom(cp, ccu); 很顺利,一次成功!下面最后一个版本了 CompileAssemblyFromSource从包含源代码的字符串的指定数组,使用指定的编译器设置编译程序集。 CompilerParameters cp = new CompilerParameters(); cp.GenerateExecutable = true; cp.OutputAssembly = "aa.exe"; cp.IncludeDebugInformation = true; cp.ReferencedAssemblies.Add("System.dll"); cp.ReferencedAssemblies.Add("System.Data.dll"); cp.ReferencedAssemblies.Add("System.Xml.dll"); cp.GenerateInMemory = false; cp.WarningLevel = 3; cp.TreatWarningsAsErrors = false; cp.CompilerOptions = "/optimize"; cp.MainClass = "simpleapp.Program"; string[] codes = new string[] { "namespace simpleapp", "{", " using System;", " class Program", " {", " static void Main(string[] args)", " {", " Console.WriteLine(/"Hello world One!/"); ", " }", " }", " class Program2", " {", " static void Main(string[] args)", " {", " Console.WriteLine(/"Hello world Two!/");", " }", " }", "}" }; CompilerResults ret = codeProvider.CompileAssemblyFromSource(cp, codes); foreach (CompilerError err in ret.Errors) { Console.WriteLine("{0}行{1}列,{2}", err.Line,err.Column, err.ErrorText); } 情况不秒,我理解的意思是第二个参数就是源代码的字符串数组啊,难道是这样? "namespace simpleapp/n"+ "{/n"+ " using System;/n"+ " class Program/n"+ " {/n"+ " static void Main(string[] args)/n"+ " {/n"+ " Console.WriteLine(/"Hello world One!/"); /n"+ " }/n"+ " }/n"+ " class Program2/n"+ " {/n"+ " static void Main(string[] args)/n"+ " {/n"+ " Console.WriteLine(/"Hello world Two!/");/n"+ " }/n"+ " }/n"+ "}" 测试,成功,哈哈!没想到真的是这样,数组的每一个元素不是代表一行代码,而是要代表一个完整的文件! CodeDom的基本模型学习完毕,还有几个其他的方法,要么和设计器有关,要么很简单,名字上就可以看出来。和设计器有关的内容下一步制作IDE开发环境的时候再研究吧!休息几天,继续研究我的Winform设计器和工作流设计器,谁有这方面经验的请多指教,工作流设计器原型已经调试好了,需要进一步完善!Winform设计器还在收集资料学习中,谁有这方面资料请贡献出来参考参考,代表所有学生感谢了!求关于System.CompomentModel和System.Drawing.Desion里面内容的详细资料,权威书籍,请各位介绍一点,本人学习后继续把心得体会记录下来! QQ:32354456 Email:diablohe@hotmail.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值