博客
关于我
从Component对象到CodeDom——舞动你的Code系列(1)
阅读量:445 次
发布时间:2019-03-06

本文共 5521 字,大约阅读时间需要 18 分钟。

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

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

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

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

下面就是具体实现:

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

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

 

public class MyComponent1 : Component    {        	public MyComponent1()        	{           		 textBox1 = new TextBox();           		 textBox1.BackColor = Color.Red;        	}	private int int1;        	private TextBox textBox1;        		public int IntProperty        	{            		get { return int1; }            		set { int1 = value; } 	}        	public TextBox TextBoxProperty        	{		get { return textBox1; }            	}}

 

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

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

 

public class CodeTypeConverter    {        private IServiceProvider _serviceProvider;        private IDesignerHost DesignerHost        {            get            {                return this._serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost;            }        }        //将Component Load到DesignerHost中并返回        private IComponent LoadComponent(IComponent component)        {            DesignSurfaceManager manager = new DesignSurfaceManager();            DesignSurface surface = manager.CreateDesignSurface();            surface.BeginLoad(component.GetType());            this._serviceProvider = surface;            IComponent newComponent = DesignerHost.RootComponent;            //暴力克隆,将component上的所有Field设到newComponent上            FieldInfo[] fields = component.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);            foreach (FieldInfo field in fields)            {                object fieldValue = field.GetValue(component);                //将所有子Component Load到DesignerHost中                if (fieldValue != null && fieldValue is IComponent)                {                    DesignerHost.Container.Add(fieldValue as IComponent, field.Name);                }                field.SetValue(newComponent, fieldValue);            }            return newComponent;        }            //将DesignerHost中的Component转成CodeType        public CodeTypeDeclaration ConvertComponentToCodeType(IComponent component)        {            component = this.LoadComponent(component) as Component;            DesignerSerializationManager manager = new DesignerSerializationManager(this._serviceProvider);            //这句Code是必须的,必须要有一个session,DesignerSerializationManager才能工作            IDisposable session = manager.CreateSession();            TypeCodeDomSerializer serializer = manager.GetSerializer(component.GetType(), typeof(TypeCodeDomSerializer)) as TypeCodeDomSerializer;            List list = new List();            foreach (IComponent item in this.DesignerHost.Container.Components)            {                list.Add(item);            }            CodeTypeDeclaration declaration = serializer.Serialize(manager, component, list);            session.Dispose();            return declaration;        }}

 

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

 

public Form1()        {            InitializeComponent();            Test();        }        public void Test()        {            CodeTypeConverter designerHost = new CodeTypeConverter();            MyComponent1 component = new MyComponent1();            component.IntProperty = 10;            component.TextBoxProperty.Text = "Hello World";            CodeTypeDeclaration componentType = designerHost.ConvertComponentToCodeType(component);            componentType.Name = component.GetType().Name + "1";            StringBuilder bulder = new StringBuilder();            StringWriter writer = new StringWriter(bulder, CultureInfo.InvariantCulture);            CodeGeneratorOptions option = new CodeGeneratorOptions();            option.BracingStyle = "C";            option.BlankLinesBetweenMembers = false;            CSharpCodeProvider codeDomProvider = new CSharpCodeProvider();            codeDomProvider.GenerateCodeFromType(componentType, writer, option);            Debug.WriteLine(bulder.ToString());            writer.Close();        }

 

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

 

public class MyComponent11 : WindowsControlLibrary1.MyComponent1{    private System.Windows.Forms.TextBox textBox1;    private MyComponent11()    {        this.InitializeComponent();    }    private void InitializeComponent()    {        this.textBox1 = new System.Windows.Forms.TextBox();        //         // textBox1        //         this.textBox1.BackColor = System.Drawing.Color.Red;        this.textBox1.Location = new System.Drawing.Point(0, 0);        this.textBox1.Name = "textBox1";        this.textBox1.Size = new System.Drawing.Size(100, 20);        this.textBox1.TabIndex = 0;        this.textBox1.Text = "Hello World";        //         //         //         this.IntProperty = 10;    }}

 

搞定收工。欢迎提问以及拍砖灌水,更欢迎掌声鲜花。

转载地址:http://qmufz.baihongyu.com/

你可能感兴趣的文章
Nginx中使用expires指令实现配置浏览器缓存
查看>>
Nginx之二:nginx.conf简单配置(参数详解)
查看>>
Nginx从入门到精通
查看>>
Nginx代理websocket配置(解决websocket异常断开连接tcp连接不断问题)
查看>>
Nginx代理初探
查看>>
nginx代理地图服务--离线部署地图服务(地图数据篇.4)
查看>>
Nginx代理外网映射
查看>>
Nginx代理模式下 log-format 获取客户端真实IP
查看>>
Nginx代理解决跨域问题(导致图片只能预览不能下载)
查看>>
Nginx代理访问提示ERR_CONTENT_LENGTH_MISMATCH
查看>>
Nginx代理配置详解
查看>>
Nginx代理静态资源(gis瓦片图片)实现非固定ip的url适配网络环境映射ip下的资源请求解决方案
查看>>
Nginx代理静态资源(gis瓦片图片)实现非固定ip的url适配网络环境映射ip下的资源请求解决方案
查看>>
Nginx使用proxy_cache指令设置反向代理缓存静态资源
查看>>
Nginx入门教程-简介、安装、反向代理、负载均衡、动静分离使用实例
查看>>
nginx反向代理
查看>>
Nginx反向代理
查看>>
nginx反向代理、文件批量改名及统计ip访问量等精髓总结
查看>>
Nginx反向代理与正向代理配置
查看>>
Nginx反向代理及负载均衡实现过程部署
查看>>