轉帖|其它|編輯:郝浩|2010-10-26 14:29:15.000|閱讀 722 次
概述:關于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@fc6vip.cn
文章轉載自:網絡轉載