为自定义配置的编辑提供”智能感知”的支持

当我们在设计一个框架的时候,必然会涉及一系列的配置。为了让使用者更好地使用你提供的框架,让他们能够容易地维护这些配置是一项基本的要求。对于一些配置过于复杂的框架,比如EnterLib,比如WCF,往往会提供一个配置的工具。但是,不过这样的配置工具是否提供,手工编译配置文件是在所难免的。如果在通过VS编辑配置的时候,能够提供智能感知和提示性描述的支持,这无疑会使配置的编辑变得非常的容易。这里是一个简单的例子。

一、配置文件的结构

假设我们设计一个MessageGenerator的组件,用于生成程序我们需要的文本消息,比如验证控件的验证消息,异常的消息等。消息的内容根据需要可以保存在数据库中或者是XML文件中,并且采用不同模式(粒度)的缓存(None、Single、Category和All)。我们采用插件式的设计,定义一个IMessageProvider接口用于从数据源中获取消息列表,两个具体的DbMessageProvider和XmlMessageProvider实现了这个接口。具体采用那个MessageProvider,通过配置来决定(defaultProvider),配置结构如下所示:

   1: <?xml version="1.0"?>
   2: <configuration>
   3:   <configSections>
   4:     <section name="artech.messages" type="Artech.Messages.MessagesSetting, Artech.Messages"/>
   5:   </configSections> 
   6:   <artech.messages defaultProvider="DbProvider" cachingMode="None">
   7:     <providers>
   8:       <add name="DbProvider"  type="Artech.Messages.DbMessageProvider, Artech.Messages" 
   9:            connectionString="" applicationName=""  />
  10:       <add name="XmlProvider" type="Artech.Messages.XmlMessageProvider, Artech.Messages" 
  11:            source="~/Messages.xml"/>      
  12:     </providers>
  13:   </artech.messages>  
  14: </configuration>

二、为配置定义XSD

为了在VS中编辑配置文件的时候获得智能感知的支持,我们需要为它定义XSD。整个XSD如下所示,结构比较清晰。不过在这里有几点需要强调:

  • 我们通过采用<xs:documentation>节点定义一些表述性的文字。当你通过VS编辑配置文件的时候,针对当前配置节点定义的这些文字将会以Tips的形式显示出来;
  • 在定义MessageProvider的schema的时候,我们将针对所有预定义MessageProvider的配置属性都定义出来(DbMessageProvider的applicationName和connectionStringName,以及XmlMessageProvider的source)。如果这些配置属性不是对于所有的MessageProvider都是必须的(比如name和type),将它们定义成可选属性;
  • 对于一些枚举,或者限定在某个列表范围内固定的值,通过<xs:restriction>/<xs:enumeration>来定义,比如这里使用到的CachingMode。
   1: <?xml version="1.0" encoding="utf-8"?>
   2: <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" >
   3:   <xs:element name="artech.messages" type="MessagesConfigSection"/>
   4:   <!--MessagesConfigSection-->
   5:   <xs:complexType name="MessagesConfigSection">
   6:     <xs:choice minOccurs="0" maxOccurs="unbounded">
   7:       <xs:element name="providers" minOccurs="1" maxOccurs="1">
   8:         <xs:complexType>
   9:           <xs:sequence>
  10:             <xs:element name="add" type="MessageProvider" minOccurs="1" maxOccurs="unbounded"/>
  11:           </xs:sequence>
  12:         </xs:complexType>
  13:       </xs:element>
  14:     </xs:choice>    
  15:     <xs:attribute name="defaultProvider" type="xs:string" use="required">
  16:       <xs:annotation>
  17:         <xs:documentation>The configuration name of the default MessageProvider.</xs:documentation>
  18:       </xs:annotation>
  19:     </xs:attribute>
  20:     <xs:attribute name="cachingMode" type="CachingMode" use="optional">
  21:       <xs:annotation>
  22:         <xs:documentation>The caching mode (None, Single, Category, All).</xs:documentation>
  23:       </xs:annotation>
  24:     </xs:attribute>    
  25:   </xs:complexType>
  26:   <!--MessageProvider-->
  27:   <xs:complexType name="MessageProvider">
  28:     <xs:attribute name="name" use="required">
  29:       <xs:annotation>
  30:         <xs:documentation>A friendly name of MessageProvider.</xs:documentation>
  31:       </xs:annotation>
  32:     </xs:attribute>
  33:     <xs:attribute name="type" type="MessageProviderTypes" use="required">
  34:       <xs:annotation>
  35:         <xs:documentation>The assembly qualified name of the MessageProvider type.</xs:documentation>
  36:       </xs:annotation>
  37:     </xs:attribute>
  38:     <xs:attribute name="connectionString" type="xs:string" use="optional">
  39:       <xs:annotation>
  40:         <xs:documentation>[DbMessageProvider]The connection string configuration name.</xs:documentation>
  41:       </xs:annotation>
  42:     </xs:attribute>
  43:     <xs:attribute name="applicationName" type="xs:string" use="optional">
  44:       <xs:annotation>
  45:         <xs:documentation>[DbMessageProvider]The name of application.</xs:documentation>
  46:       </xs:annotation>
  47:     </xs:attribute>
  48:     <xs:attribute name="source" type="xs:string" use="optional">
  49:       <xs:annotation>
  50:         <xs:documentation>[XMLMessageProvider] The path of the XML file to store message entry list.</xs:documentation>
  51:       </xs:annotation>
  52:     </xs:attribute>
  53:   </xs:complexType>
  54:   <!--CachingMode-->
  55:   <xs:simpleType name="CachingMode">
  56:     <xs:restriction base="xs:string">
  57:       <xs:enumeration value="None"/>
  58:       <xs:enumeration value="Single"/>
  59:       <xs:enumeration value="Category"/>
  60:       <xs:enumeration value="All"/>
  61:     </xs:restriction>
  62:   </xs:simpleType>
  63:   <!--MessageProviderTypes-->
  64:   <xs:simpleType name="MessageProviderTypes">
  65:     <xs:restriction base="xs:string">
  66:       <xs:enumeration value="Artech.Messages.DbMessageProvider, Artech.Messages"/>
  67:       <xs:enumeration value="Artech.Messages.XmlMessageProvider, Artech.Messages"/>
  68:     </xs:restriction>
  69:   </xs:simpleType>
  70: </xs:schema>

三、应用XSD以获得职能感知的支持

如果这样一个XSD已经定义好,在对配置文件进行编辑的时候,通过VS的菜单XML\Schemas打开XML Schemas对话框。点击Add按钮将这个XSD文件添加近来,并Use属性设置成Use this schema。这样你编译配置文件的时候就可以获得只能感知的支持了,配置将会变得非常的容易,即使对配置结构不太了解的人也能根据智能感知和提示性的描述完成配置工作。

为自定义配置的编辑提供”智能感知”的支持


作者:蒋金楠
微信公众账号:大内老A
微博:www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
上一篇:【0907 - 0911直播导视 | PPT 下载】开源系列直播开播啦、手把手带你 5 步上手 Kubernetes!


下一篇:Flutter 56: 图解自定义 BubbleWidget 气泡插件