彩票走势图

如何让一个Component对象生成CodeDom

转帖|其它|编辑:郝浩|2010-10-26 14:29:15.000|阅读 711 次

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

# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>

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

  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,对于具体实现我不做过多的说明,你不必要关心实现的具体细节,只要这个实现能够满足你的需求就行了。如果你有看不明白的地方请提问,我会认真回答。

  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方法测试:

  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跑起来以后,就可以在输出窗口看到如下的输出:

  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 }


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn

文章转载自:网络转载

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP