SharpDevelop 属性结构分析

属性结构位于Core/Property,先看属性系统的工作方式,如图:
SharpDevelop 属性结构分析

IXmlCovartable接口提供了对象与XML节点互相转换的方法,可以认为是序列化的另一种实现方式。据作者说,这两个方法的实现要比序列化速度快很多。
IProperties是主接口,应用程序其他部分都通过调用该接口进行工作。它提供了对属性的读写操作,以及一个自身对象的复制方法。

DefaultProperties是IProperties接口的默认实现方式,其中的几个实现方法确实有点意思。
这个类其实是个注册工厂,所有属性按需创建,都存在properties这个hashtable中。

1.先说

1.先说GetProperty(),这个方法有若干重载,见下:
 1           public   object  GetProperty( string  key,  object  defaultvalue)
 2          {
 3               if  ( ! properties.ContainsKey(key)) {
 4                   if  (defaultvalue  !=   null ) {
 5                      properties[key]  =  defaultvalue;
 6                  }
 7                   return  defaultvalue;
 8              }
 9              
10               object  obj  =  properties[key];
11              
12               if  (defaultvalue  is  IXmlConvertable  &&  obj  is  XmlElement) {
13                  obj  =  properties[key]  =  ((IXmlConvertable)defaultvalue).FromXmlElement((XmlElement)((XmlElement)obj).FirstChild);
14              }
15               return  obj;
16          }
2-8行是在hashtable中找不到key的处理办法:即新建key并设为defaultvalue,同时返回defaultvalue。
10-15行,如果hashtable中有这个key,那么取出来赋值给obj。如果defaultvalue派生自IXmlCovertable接口同时obj又是XmlElement——13行就难看懂了,真奇怪为什么牛人都喜欢写这么长的语句。把它拆开就是:
            XmlNode node  =  ((XmlElement)obj).FirstChild;
            XmlElement element 
=  (XmlElement)node;                  //key值应该对应obj的第一个字节点

            IXmlConvertable ixc 
=  (IXmlConvertable)defaultvalue;    // 将DefaultValue拆箱为IXmlConvertable

            
object  temp  =  ixc.FromXmlElement(element);

            obj 
=  properties[key]  =  temp;

看到这里,发现defaultvalue在这里不起任何作用,因为 FromXmlElement()方法只是创建了一个以 element为基础的新的DefaultProperties对象。所以可以简写为
            XmlNode node  =  ((XmlElement)obj).FirstChild;
            XmlElement element 
=  (XmlElement)node;    // 这里element就是obj对象的一个clone

            
object  temp  =  FromXmlElement(element);

            obj 
=  properties[key]  =  temp;

这也就是第13行的意思,既然hashtable中有这个key值,就把它取出来,得到它的第一个子节点,以此为基础重新构造出一个新对象,赋予obj并返回。——这里我不太明白,需要debug到Runtime才会领悟。

补注:GetProperty有一个Enum版的重载,对我们写程序很有参考价值:
   
         public  System.Enum GetProperty( string  key, System.Enum defaultvalue)
        {
            
try  {
                
return  (System.Enum)Enum.Parse(defaultvalue.GetType(), GetProperty(key, ( object )defaultvalue).ToString());
            } 
catch  (Exception) {
                
return  defaultvalue;
            }
        }


2.SetProperty(string key, object val)
    如果新旧属性值不同,就为该key设置新的属性,并激发事件OnPropertyChanged,这是一个virtual可覆写的事件,不同的场景对该事件有不同的实现,这个事件的自定义参数PropertyEventArgs继承了EventArgs,并随身携带着key/oldValue/newValue。

3.FromXmlElement():根据XmlElement参数构造出一个新的DefaultProperty对象来,需要辅助函数SetValueFromXmlElement()的配合:

         public   virtual   object  FromXmlElement(XmlElement element)
        {
            DefaultProperties defaultProperties 
=   new  DefaultProperties();
            defaultProperties.SetValueFromXmlElement(element);
            
return  defaultProperties;
        }

        
protected   void  SetValueFromXmlElement(XmlElement element)
        {
            XmlNodeList nodes 
=  element.ChildNodes;
            
foreach  (XmlElement el  in  nodes)
            {
                
if  (el.Name  ==   " Property " )
                {
                    properties[el.Attributes[
" key " ].InnerText]  =  el.Attributes[ " value " ].InnerText;
                }
                
else   if  (el.Name  ==   " XmlConvertableProperty " )
                {
                    properties[el.Attributes[
" key " ].InnerText]  =  el;
                }
                
else
                {
                    
throw   new  UnknownPropertyNodeException(el.Name);
                }
            }
        }

SetValueFromXmlElement()方法,需要参考data\options\SharpDevelopProperties.xml文件,以理解一个新的属性对象是如何构造出来的。

4.ToXmlElement():与FromXmlElement()功能正好相反,不多说了。


你可能感兴趣的:(sha)