zoukankan      html  css  js  c++  java
  • DotText源码阅读(3)框架配置体系和反序列化

     dottext框架配置体系 和反序列化
     
    配置节是一个比较容易混淆人的专题。Dottext的系统环境配置、单独每一个人的blog配置都是通过自定义的配置节实现的,并且dottext自己实现了其中的处理程序(handler)。也就是说,利用asp.net系统的配置文件作为存储机制,加上了单独处理机制,实现了系统的灵活配置。
    在web.config的根元素<configuration>下一开始就声明了自定义配置节处理程序:
    <configSections>
                  <section name="BlogConfigurationSettings" type="Dottext.Framework.Util.XmlSerializerSectionHandler, Dottext.Framework" />
                  <section name="HandlerConfiguration" type="Dottext.Framework.Util.XmlSerializerSectionHandler, Dottext.Framework" />
                  <section name="SearchConfiguration" type="Dottext.Framework.Util.XmlSerializerSectionHandler, Dottext.Framework" />
                  <section name="microsoft.web.services" type="Microsoft.Web.Services.Configuration.WebServicesConfiguration, Microsoft.Web.Services, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
                  <section name="codeHighlighter" type="ActiproSoftware.CodeHighlighter.CodeHighlighterConfigurationSectionHandler, ActiproSoftware.CodeHighlighter" />
    </configSections>
     
    其中的最后2项自然不必多讲,属于微软的提供程序和第三方提供程序,在此忽略。我们逐步来看看 Dottext.Framework.Util 下的实现过程,理解其中的逻辑。
    用到的自定义处理程序都是 XmlSerializerSectionHandler ,我们看看其中的处理逻辑,蕴含的.net特性:
     
    public object Create(object parent, object configContext, System.Xml.XmlNode section)
                  {
                         XPathNavigator nav = section.CreateNavigator();
                         string typename = (string) nav.Evaluate("string(@type)");
                         Type t = Type.GetType(typename);
                         XmlSerializer ser = new XmlSerializer(t);
                         return ser.Deserialize(new XmlNodeReader(section));
    }
    string typename = (string) nav.Evaluate("string(@type)"); 是从当前XML(配置文件是一个符合xml要求的文档)节点处,获取”type”属性,然后按照属性描述,获得一个.net的类型。这里使用到了.net的反射机制。此处的type可以是类 、值类型 、数组 、接口 、指针 、枚举类型。这样,通过配置文件中的xml流(相当于字符串),系统就指定了特定的类。这种生成类的方法是区别于new 方法生成具体类的另外途径,好处就是灵活根据具体环境内容(甚至是用户交互输入的类型描述字符串)就可以生成获得托管类型。(此处反射细节请参考MSDN)。坏处就是可能隐藏着类型错误,运行时出错,导致不可预料(好像这个词在windows编程时代相当的常见)例外甚至系统崩溃。
    当然,仅仅创建了类型是不够用的,还需要通过一定途径来确定生成类的具体状态,这有用到OOP语言的重要特性—序列化,将一个对象存储器来,以及从存储中还原具体对象的机制。这里使用的是System提供的 XmlSerializer 类的反序列化方法Deserialize。反序列化后面还有很多代码涉及到,我认为现在就大致理解为“通过这个反序列化,我们刚刚得到的类实例中的属性、成员变量获得了赋值,进入到某个状态,就好像我们此处运行了new 语法和进行了对象的构造以及赋值”即可。更进一步的可以从权威资料MSDN获取。
     
    基于以上理解,我们来阅读相关的配置节,并进行解释。
    从简单的入手:
    <SearchConfiguration type="Dottext.Search.SearchConfiguration, Dottext.Search" urlFormat="http://{0}/{1}/{2}/{3}.aspx"
                  virtualPath ="~/SearchIndex" physicalPath="\SearchIndex" domains="localhost"
                  pageSize="20" />
    这个配置节,定义了一个 在Dottext.Search程序集中存在的名为“Dottext.Search.SearchConfiguration”的类,在反序列化的时候,我们会对其中的某些属性(urlFormat、virtualPath、physicalPath、domains、pageSize )进行赋值。那么,这些可以反序列化的类有否什么区别于其他“正常类”的地方呢?我们打开这个类看看:
    [Serializable]       //注意,这里用到的是属性编程,这个是.net的新特性,通过这个语法声明了名为Serializable的属性给类 SearchConfiguration,告诉.net框架这个类是可以进行序列化和反序列化。默认情况下,所有该类的字段(包括私有)都要序列化和反序列化,但是通过另外指定属性声明,可以灵活处理。
           public class SearchConfiguration
           {
                  public static readonly string PermaLink = "permalink";
                  。。。。。。//一大堆只读静态字段
                  public static readonly string TempIndex = "tempIndex";
                 
                  public static SearchConfiguration Instance()
                  {
                         return (SearchConfiguration)ConfigurationSettings.GetConfig("SearchConfiguration");
    //此处就是利用了反射来构造类实例。
                  }
     
                  public SearchConfiguration()
                  {                     //缺盛构造函数
                  }
     
                  private string _urlFormat = "http://{0}/{1}/{2}/{3}.aspx";
                  [XmlAttribute("urlFormat")]       //此处另外声明了UrlFormat属性的序列化和反序列化属性,告诉.net运行时环境此处的字段采用XML节点作为存储进行序列化和反序列化,并且读取的节点名称是“urlFormat”。
                  public string UrlFormat
                  {
                         get {return this._urlFormat;}
                         set {this._urlFormat = value;}
                  }
     
                  private string _domains;
                  [XmlAttribute("domains")]
                  public string Domains
                  {
                         get {return this._domains;}
                         set {this._domains = value;}
                  }
     
                  private int _rebuildInterval = 60;                    
                  [XmlAttribute("rebuildInterval")]
                  public int RebuildInterval
                  {
                         get {return this._rebuildInterval;}
                         set {this._rebuildInterval = value;}
                  }
     
                  private int _updateInterval = 30;             
                  [XmlAttribute("updateInterval")]
                  public int UpdateInterval
                  {
                         get {return this._updateInterval;}
                         set {this._updateInterval = value;}
                  }
     
                  private int _pageSize = 50;         
                  [XmlAttribute("pageSize")]
                  public int PageSize
                  {
                         get {return this._pageSize;}
                         set {this._pageSize = value;}
                  }
     
                  private int _searchResultLimit = 100;       
                  [XmlAttribute("searchResultLimit")]
                  public int SearchResultLimit
                  {
                         get {return this._searchResultLimit;}
                         set {this._searchResultLimit = value;}
                  }
     
                  private string _virtualPath;             
                  [XmlAttribute("virtualPath")]
                  public string VirtualPath
                  {
                         get {return this._virtualPath;}
                         set {this._virtualPath = value;}
                  }
     
                  private string _physicalPath;         
                  [XmlAttribute("physicalPath")]
                  public string PhysicalPath
                  {
                         get
                         {
                                if(this._physicalPath == null)
                                {
                                       if(VirtualPath != null)
                                       {
                                              this._physicalPath = HttpContext.Current.Server.MapPath(VirtualPath);
                                       }
                                       else
                                       {
                                              throw new ApplicationException("Physical location of the search index could not be found. Either the physical or virtual location must be specified in your configuration file");
                                       }
                                }
                                return this._physicalPath;
                         }
                         set {this._physicalPath = value;}
                  }
           }
     
    如果哪一个字段不需要参与序列化和反序列化,应该指定[XmlIgnore]属性标记。
     
    接下来,看看后面经常用到的 BlogConfigurationSettings ,该类为“Dottext.Framework.Configuration.BlogConfigurationSettings”,察看该类源代码,我们发现该类也是可序列化和反序列化的。不过注意的是,其中的部分成员属于数组,而数组属于复合数据类型,所以在配置文件声明中是这样的:
    <EntryHandlers>
                         <EntryHandler type="Dottext.Framework.EntryHandling.CommentFormatHandler, Dottext.Framework" postType="Comment"       processAction="Insert" processState="PreCommit" isAsync="false" />
                         <EntryHandler type="Dottext.Framework.EntryHandling.CommentDeliveryHandler, Dottext.Framework"       postType="Comment" processAction="Insert" processState="PostCommit" isAsync="true" />
                          ……
    </EntryHandlers>
    而在类源代码中是这样的来说明改成员:
    private EntryHandler[] _entryHandlers;
    [XmlArray("EntryHandlers")]
    public EntryHandler[] EntryHandlers
    {
           get {return this._entryHandlers;}
           set {this._entryHandlers = value;}
    }
    通过XmlArray属性,指出了要按照数组方式进行序列化和反序列化,节点的名称是“EntryHandlers”。.net CLR会通过反射机制将配置文件的描述生成EntryHandler[],而其中每一个元素都是Dottext.Framework.EntryHandling.CommentDeliveryHandler,这个过程通过一个短小的[XmlArray("EntryHandlers")]就完成,且又达到了灵活是应需求,展示了.net提供的新特性的威力。HandlerConfiguration也是通过配置获得一个数组,类似机理。
    另外,打击需要着重看看
    <BlogProviders>
                         <!-- Controls how .Text formats Urls -->
                         <UrlFormatProvider type="Dottext.Framework.Format.UrlFormats, Dottext.Framework" />
                         <DTOProvider type="Dottext.Framework.Data.DataDTOProvider, Dottext.Framework" />
                         <!--
                                       By default .Text uses SQL Server as the backend data store. The DbProvider determines which DbProvider
                                       (a class which implements IDbProvider) is used. This is optional.
                         -->
                         <DbProvider type="Dottext.Framework.Data.SqlDataProvider, Dottext.Framework" connectionString="user id=ad;password=cbiqadjsd;initial Catalog=Zixun_dataBase;Data Source=211" />
                         <ConfigProvider type="Dottext.Common.Config.MultipleBlogConfig, Dottext.Common" host="localhost"       cacheTime="120" />
                         <!--
                         <ConfigProvider type = "AspNetWeb.MSBlogsConfigProvider, MsftBlogsHttpModule"
                                cacheTime = "120"/>
                         -->
                         <!-- Controls how .Text sends email. By default, SystemMail is used. -->
                         <EmailProvider type="Dottext.Framework.Email.SystemMail, Dottext.Framework" smtpServer="localhost"       adminEmail="EMAIL" />
                  </BlogProviders>
    此处的配置信息在后面的很多部分都涉及到。看看BlogProviders类(呵呵,当作课外吧),也是一个可序列化和反序列化的类。
    整个dottext很多灵活性就是通过这机制体现。
  • 相关阅读:
    为什么 PCB 生产时推荐出 Gerber 给工厂?
    Fedora Redhat Centos 有什么区别和关系?
    【KiCad】 如何给元件给元件的管脚加上划线?
    MCU ADC 进入 PD 模式后出现错误的值?
    FastAdmin 生产环境升级注意
    EMC EMI 自行评估记录
    如何让你的 KiCad 在缩放时不眩晕?
    KiCad 5.1.0 正式版终于发布
    一次单片机 SFR 页引发的“事故”
    java基础之集合
  • 原文地址:https://www.cnblogs.com/jasononline/p/767192.html
Copyright © 2011-2022 走看看