CodeSmith基础(八)

编写CodeSmith自定义属性的编辑器(Writing Custom Property Editors)
        当你开始编写自定义的 CodeSmith 模板时,很可能对于使用它的 strings integers 属性很满意,但有时你会发现需要创建一个不同类型的属性,可能是一个自定义的类型或者是 .NET framework 中但是在属性面板中没有提供的类型。在模板中去作这些很简单,但是怎样指定一个类型在运行模板时显示在属性面板中呢?例如创建了一个 Person 类并且具有很多不同的属性,但是却没有办法让用户去组装这个类……除非创建一个自定义属性编辑器。
        属性面板提供了方法去编写自定义的属性编辑器,当用户在面板上选择一个属性时可以激发相应的方法,同时也可以通过编写代码实现提示用户输入一个必要的值。下面我们举个例子,创建一个接受组建的属性并且是用影射循环贯串所有的类,是所有的类都可以使用它和它的方法,去创建一个 NUnit 测试基础。(这句翻译的不好,原文: As an example we are going to build a template which accepts an assembly as a property and then using reflection loops through all of the classes, and the methods of those classes, to build NUnit test stubs.
        首先,我们来关注一下模板的组件属性,暂且不看自定义编写的代码。模板的第一部分是一些声明定义和属性。将属性放在脚本标签中代替使用属性声明,在下一部分将看到这样做的必要。
 1 <% @ CodeTemplate Language = " C# "  TargetLanguage = " C# "  Description = " Builds a class for each class in the assembly, and a test stub for every method. "   %>
 2
 3 <% @ Import NameSpace = " System.Reflection "   %>
 4
 5 < script runat = " template " >
 6
 7 private  Assembly assembly;
 8
 9 public  Assembly AssemblyToLoad
10 {
11      get{return assembly;}
12      set{assembly = value;}
13}

14
15 </ script >
        然后我们为组建 assembly 中的每一个类创建一个类,为每一个类创建他的方法。然后直接将模板的输出内容放入 Visual Studio.NET ,然后在编写组件的单元测试时使用向导。
 1 using  System;
 2 using  NUnit.Framework;
 3
 4 <%
 5        foreach (Type T  in  AssemblyToLoad.GetTypes())
 6        {
 7            if(T.IsClass)
 8            {
 9                  %>
10
11                  [TestFixture]
12                  public class <%=T.Name%>Tests
13                  {
14                  <%
15                              MethodInfo[] methods = T.GetMethods ( BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static  );
16                              foreach(MethodInfo M in methods)
17                              {
18                                    %>
19
20                                    [Test]
21                                    public void <%=M.Name%>Test
22                                    {
23                                          //TODO Write this test
24                                    }
                 
25                                    <%
26                              }

27
28                  %>}
<%
29            }

30      }

31 %>
        这个模板仅仅可以编译通过,但是由于我们编写显示了一个类型属性面板并不知道如何去操作它,所以我们没有办法自定义指定组件在加载时想要加载的组件。
        我们需要创建一个 UITypeEditor ,这是一个建立属性面板是用的特殊属性的类。 UITypeEditor 需要创建在一个和模板分离的组件中,我们是用 Visual Studio 创建这个类。
 /Files/Bear-Study-Hard/AssemblyHelper.zip
        首先我们需要创建一个继承 UITypeEditor 的类。
1 public   class  AssemblyFilePicker : UITypeEditor
2 {
3      public AssemblyFilePicker(): base()
4      {
5      }

6}
        关于 UITypeEditor 的说明请大家参看 M SD N Visual Studio.NET 自带帮助中的说明,其中有详细的例子。
        然后我们需要重载 UITypeEditor 类的两个不同的方法。第一个需要重载点的方法是 GetEditStyle ,这个方法是告诉属性面板对于当前类型是用什么类型的编辑器,在这个例子中我们设置编辑类型为 Modal 。这样大家可以在该属性格子的右边看到一个小按钮,它将引发一个对话框等模式的对话( trigger a modal dialog )。这是我们的 GetEditStyle 方法:
1 public   override  UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) 
2 {
3      return UITypeEditorEditStyle.Modal;
4}
        其中的Modal为显示一个省略号按钮。
        需要重载的另一个方法是 EditValue 方法,当用户电击属性时会调用这个方法。按照我们需要加载的组件类型需要创建一个打开文件对话框( open file dialog )然后捕获这个对话框,在属性格子中返回对话框的结果。
1 public   override   object  EditValue(ITypeDescriptorContext context, IServiceProvider provider,  object  value)
2 {
3
4if (provider != null
5{
        首先我们要从当前的服务和控件中得到一个参考,有了控件的参考我们可以通过它转到ShowDialog方法。(原文:First we need to get a reference to the current service and control, we need the reference to the control so we can pass it to the ShowDialog method.
1 IWindowsFormsEditorService editorService  =  (IWindowsFormsEditorService)provider.GetService( typeof (IWindowsFormsEditorService));
2 Control editorControl  =  editorService  as  Control;
3
4 if  (editorControl  !=   null
5 {
        然后我们创建一个openFileDialog类并填入适合的属性。
1 OpenFileDialog openFileDialog  =   new  OpenFileDialog();                         
2
3 openFileDialog.CheckFileExists  =   true ;
4 openFileDialog.DefaultExt  =   " .dll " ;
5 openFileDialog.Multiselect  =   false ;
6 openFileDialog.Title  =   " Select an Assembly: " ;
7 openFileDialog.Filter  =   " Assembly Files | *.dll " ;
        然后我们通过控件的参考(reference)将对话框显示给用户。
1 DialogResult result  =  openFileDialog.ShowDialog(editorControl);
        下一步我们检查用户是否点击了OK按钮,如果点击了,通过文件选择对话框选择文件后使用LoadForm方法加载这个组件,最后返回这个值。
 1 if  (result  ==  DialogResult.OK)
 2              {
 3Assembly assembly = Assembly.LoadFrom( openFileDialog.FileName ) ;
 4                  value = assembly; 
 5            }

 6              else
 7              {
 8                  value = null;
 9            }

10       }
11 }
12
13 return  value;
14 }
        这个值将被放在属性面板中并可以被模板读取,但是需要注意,在我们作这个之前要将组件import引入到模板中,并在模板中用一对属性声明。
        加载这个模板我们仅需将这个组件 assembly 与模板放在同一目录下,然后再模板中加入下面两行代码。
1 < %@ Assembly  Name ="AssemblyHelper"  % >
2 < %@ Import  NameSpace ="AssemblyHelper"  % >
        然后我们要在组建属性中添加Editor属性,并且指定为UITypeEditor编辑器。
1 [Editor( typeof (AssemblyHelper.AssemblyFilePicker),  typeof (System.Drawing.Design.UITypeEditor))]
2 public  Assembly AssemblyToLoad
3 {
4      get{return assembly;}
5      set{assembly = value;}
6}
        当属性面板读取到这些属性时,它将使用我们自定义的 UITypeEditor 编辑器并允许用户从打开文件对话框中选择一个组件。

本文出自 “努力学习的小熊” 博客,转载请与作者联系!

分享至
一键收藏,随时查看,分享好友!
0人
了这篇文章
类别: CodeSmith使用┆阅读( 0)┆评论( 0) ┆ 返回博主首页┆ 返回博客首页
上一篇 在框架中自动撑大iframe的高度 下一篇 base关键字的说明(学习使用)

相关文章

  • 使CodeSmith可以直接生成代码到文件
  • CodeSmith,SqlServer,C#中的类型对照
  • 项目管理基础
  • BGP基础-community属性试验

职位推荐

  • web前端开发工程师
  • 前端工程师
  • 云平台应用开发工程师
  • 高级PHP开发工程师
  • 后端开发工程师

文章评论

 
 

发表评论            

昵  称:
登录  快速注册
验证码:

点击图片可刷新验证码请点击后输入验证码博客过2级,无需填写验证码

内  容:

同时赞一个

你可能感兴趣的:(基础,职场,休闲,codesmith)