控件中国网现已改版,您看到的是老版本网站的镜像,系统正在为您跳转到新网站首页,请稍候.......
中国最专业的商业控件资讯网产品咨询电话:023-67870900 023-67871946
产品咨询EMAIL:SALES@COMPONENTCN.COM

从Component对象到CodeDom——舞动你的Code系列(1)

作者:Dxy 出处:博客 2010年08月31日 阅读:

我们经常会有这样的需求或者想法:动态的生成或者修改代码。当然,我们可以把代码看成字符串而直接修改,但是这种做法也未免太生硬了,能解决的问题有限;而另一个方式就是CodeDom。

CodeDom是强大的!我们感谢微软,给我们提供了强大的描述面向对象语言的框架;我们感谢微软,给我们提供了能够根据CodeDom生成代码或者程序集的CodeDomProvider;可惜微软没有给我们提供能够从object或者代码生成CodeDom的能力。

关于CodeDom的知识本文不过多涉及、感兴趣的童鞋可以阅读MSDN或者博客园的其它文章学习了解。本系列期望解决的问题就是如何将对象或者代码生成CodeDom。当然,由于微软并没有提供这样的支持,而我也不可能写一个解析C#语言或者VB语言的CodeParser,所以本文提供的方案也能力有限,但愿能够解决你的一部分问题或者给您能学到点知识。

这是本系列的第一篇文章,如何让一个Component对象生成CodeDom。核心思想就是虚拟一个DesignTime的环境,并将Component添加到Designer中,然后使用ComponentTypeCodeDomSerializer将Component序列化成CodeTypeDeclaration。本方案可以在任意程序下执行,不依赖IDE,也不需要引用各种奇怪的dll。

下面就是具体实现:

首先,创建一个WindowsControlLibrary,名叫WindowsControlLibrary1。

然后,添加一个类取名MyComponent1,类中有一个GetSet的属性IntProperty,还有一个设置了背景色的TextBox:

01 public class MyComponent1 : Component    
02 {        
03     public MyComponent1()        
04     {           
05          textBox1 = new TextBox();           
06          textBox1.BackColor = Color.Red;        
07     }
08   
09     private int int1;        
10     private TextBox textBox1;        
11       
12     public int IntProperty        
13     {            
14         get { return int1; }            
15         set { int1 = value; } 
16     }        
17   
18     public TextBox TextBoxProperty        
19     {
20         get { return textBox1; }            
21     }
22 }

 

接着创建另一个WindowsFormsApplication项目:CodeDomSample,并引用System.Design和WindowsControlLibrary1项目(当然,你也可以把WindowsControlLibrary1编译成dll并引用这个dll)

现在,创建我们的核心类CodeTypeConverter,对于具体实现我不做过多的说明,你不必要关心实现的具体细节,只要这个实现能够满足你的需求就行了。如果你有看不明白的地方请提问,我会认真回答。

01     public class CodeTypeConverter
02     {
03         private IServiceProvider _serviceProvider;
04   
05         private IDesignerHost DesignerHost
06         {
07             get
08             {
09                 return this._serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost;
10             }
11         }
12   
13         //将Component Load到DesignerHost中并返回
14         private IComponent LoadComponent(IComponent component)
15         {
16             DesignSurfaceManager manager = new DesignSurfaceManager();
17             DesignSurface surface = manager.CreateDesignSurface();
18             surface.BeginLoad(component.GetType());
19             this._serviceProvider = surface;
20             IComponent newComponent = DesignerHost.RootComponent;
21             //暴力克隆,将component上的所有Field设到newComponent上
22             FieldInfo[] fields = component.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
23             foreach (FieldInfo field in fields)
24             {
25                 object fieldValue = field.GetValue(component);
26                 //将所有子Component Load到DesignerHost中
27                 if (fieldValue != null && fieldValue is IComponent)
28                 {
29                     DesignerHost.Container.Add(fieldValue as IComponent, field.Name);
30                 }
31                 field.SetValue(newComponent, fieldValue);
32             }
33             return newComponent;
34         }
35       
36         //将DesignerHost中的Component转成CodeType
37         public CodeTypeDeclaration ConvertComponentToCodeType(IComponent component)
38         {
39             component = this.LoadComponent(component) as Component;
40             DesignerSerializationManager manager = new DesignerSerializationManager(this._serviceProvider);
41             //这句Code是必须的,必须要有一个session,DesignerSerializationManager才能工作
42             IDisposable session = manager.CreateSession();
43             TypeCodeDomSerializer serializer = manager.GetSerializer(component.GetType(), typeof(TypeCodeDomSerializer)) as TypeCodeDomSerializer;
44             List<object> list = new List<object>();
45             foreach (IComponent item in this.DesignerHost.Container.Components)
46             {
47                 list.Add(item);
48             }
49             CodeTypeDeclaration declaration = serializer.Serialize(manager, component, list);
50             session.Dispose();
51             return declaration;
52         }
53 }

好了,CodeTypeConverter实现完成。现在在Form1中写一个Test方法测试:

01 public Form1()
02 {
03     InitializeComponent();
04     Test();
05 }
06  
07 public void Test()
08 {
09     CodeTypeConverter designerHost = new CodeTypeConverter();
10     MyComponent1 component = new MyComponent1();
11     component.IntProperty = 10;
12     component.TextBoxProperty.Text = "Hello World";
13  
14     CodeTypeDeclaration componentType = designerHost.ConvertComponentToCodeType(component);
15     componentType.Name = component.GetType().Name + "1";
16  
17     StringBuilder bulder = new StringBuilder();
18     StringWriter writer = new StringWriter(bulder, CultureInfo.InvariantCulture);
19     CodeGeneratorOptions option = new CodeGeneratorOptions();
20     option.BracingStyle = "C";
21     option.BlankLinesBetweenMembers = false;
22     CSharpCodeProvider codeDomProvider = new CSharpCodeProvider();
23     codeDomProvider.GenerateCodeFromType(componentType, writer, option);
24     Debug.WriteLine(bulder.ToString());
25     writer.Close();
26 }

CodeDomSample跑起来以后,就可以在输出窗口看到如下的输出:

01 public class MyComponent11 : WindowsControlLibrary1.MyComponent1
02 {
03     private System.Windows.Forms.TextBox textBox1;
04     private MyComponent11()
05     {
06         this.InitializeComponent();
07     }
08     private void InitializeComponent()
09     {
10         this.textBox1 = new System.Windows.Forms.TextBox();
11         // 
12         // textBox1
13         // 
14         this.textBox1.BackColor = System.Drawing.Color.Red;
15         this.textBox1.Location = new System.Drawing.Point(0, 0);
16         this.textBox1.Name = "textBox1";
17         this.textBox1.Size = new System.Drawing.Size(100, 20);
18         this.textBox1.TabIndex = 0;
19         this.textBox1.Text = "Hello World";
20         // 
21         // 
22         // 
23         this.IntProperty = 10;
24     }
25 }

热推产品

  • ActiveReport... 强大的.NET报表设计、浏览、打印、转换控件,可以同时用于WindowsForms谀坔攀戀Forms平台下......
  • AnyChart AnyChart使你可以创建出绚丽的交互式的Flash和HTML5的图表和仪表控件。可以用于仪表盘的创......
首页 | 新闻中心 | 产品中心 | 技术文档 | 友情连接 | 关于磐岩 | 技术支持中心 | 联系我们 | 帮助中心 Copyright-2006 ComponentCN.com all rights reserved.重庆磐岩科技有限公司(控件中国网) 版权所有 电话:023 - 67870900 传真:023 - 67870270 产品咨询:sales@componentcn.com 渝ICP备12000264号 法律顾问:元炳律师事务所 重庆市江北区塔坪36号维丰创意绿苑A座28-5 邮编:400020
在线客服
在线客服系统
在线客服
在线客服系统