说说C#下的动态可配置的扩展

前几天给一个系统做了一个小模块,类似于一个tab组件,和主程序关系不大。但是tab的page页需要根据实际情况进行扩展,同时每个page页的表现都不一样(根据具体需求变动),并且希望这个扩展可以通过外部配置文件配置(类似于Plusin)。

开始没有什么头绪,后来想到扩展的部分可以通过继承的方式实现,在基类中定义输出表现的虚函数,然后在扩展的子类中实现该虚方法,实现自己的表现。通过这种“多态”,实现了扩展的要求。对于新的扩展机能,只需要从该基类继承,实现相应的虚方法,就达到了扩展的目的,而且一点也不影响既存的技能。

对于可配置方面,想通过反射的机制来实现,将扩展的类名声明到配置文件中,使用C#的反射机制,加载具体的子类,以实现可配置的要求。

下面用代码简单的说明一下:


基类的定义:       

    public class Container 
    {
        
private string ContainerNameField;
        
private string DataField;
        
private int IndexField;

        [Serialize(
true)]
        
public string ContainerName
        {
            
get
            {
                
return this.ContainerNameField;
            }
            
set
            {
                
this.ContainerNameField = value;
            }
        }
      
        [Serialize(
true)]
        
public string Data
        {
            
get
            {
                
return this.DataField;
            }
            
set
            {
                
this.DataField = value;
            }
        }

        [Serialize(
true)]
        
public int Index
        {
            
get
            {
                
return this.IndexField;
            }
            
set
            {
                
this.IndexField = value;
            }
        }
    
        
//需要实现的虚函数,默认直接返回数据,不做任何处理
        public virtual string ToHtml()
        {
            
return this.Dtat;
        }
    }

 

实现扩展子类:

①表现内存数

    public class MemorySizeContainer  : Container 
    {
        
public override string ToHtml()
        {
            
string result = "";
            
int size = int.Parse(base.Data);

            
if (size == 0)
            {
                result 
= "当前内存的为1GB以下";
            }
            
else if (size > 1)
            {
                result 
= string.Format("当前内存的为{0}~{1}GB", size, size + 1);
            }
            
return result;
        }

     }


②表现硬件状态

    public class HardwareStatusContainer : Container
    {
        
public override string ToHtml()
        {
            HardwareStatus status 
= Utility.ToEnum(HardwareStatus, base.Data);
            
switch (status)
            {
                
case HardwareStatus.Ready:
                    
return "正常";

                case HardwareStatus.Faulted:    

                    return "故障";

                case HardwareStatus.Degraded:
                    
return "部分故障";
                
case HardwareStatus.Unknown:
                    
return "未知";
                
default:
                    
return "未知";
            }
        }
    }
 

 


...... 

配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<Configuration>

    
<!--Containers-->
    
<Containers>
      
<!--HardwareStatus-->
      
<Container>
        
<Type>HardwareStatus</Type>

        <ContainerName>硬件状态</ContainerName>
        <Index>0</Index> 
       <Class>Serialize.TabContainer.HardwareStatusContainer</Class>

      </Container>

      
<!--Memory-->
      
<Container>
        
<Type>Memory</Type>

        <ContainerName>内存</ContainerName>
        <Index>1</Index>
        <Class>Serialize.TabContainer.MemorySizeContainer </Class>
      </Container>

    </Containers>  
</Configuration>

 


反射加载:

    public Container ContainerFactory(string pageType, string data)
    {
        
string section = "/Configuration/Containers/Container";
        
string condition = "[Type='" + pageType + "']";
        
string ContainerName = GetValueByCondition(section, "ContainerName", condition);
        
string Class = GetValueByCondition(section, "Class", condition);
        
string index = GetValueByCondition(section, "Index", condition);

        
if ( !string.IsNullOrEmpty(ContainerName) &&
             
!string.IsNullOrEmpty(Class) &&
             
!string.IsNullOrEmpty(index) )
        {
            Type type 
= Type.GetType(Class);
            Container container 
= (Container )Activator.CreateInstance(type, true);
            container.ContainerName 
= ContainerName;
            container.Index 
= index;
            container.Data 
= data;

            
return container;
        }
        
else
        {
            
return null;
        }
    }

    
private string GetValueByCondition(string section, string key,string condition)
    {
        
try
        {
            String xPathString 
= "/" + section + condition + "/" + key;
            XPathNavigator navigator 
= this.document.CreateNavigator();
            XPathNodeIterator nodeIter 
= ( XPathNodeIterator )navigator.Evaluate(xPathString);

            
if ((nodeIter.Count == 1&& (nodeIter.MoveNext()))
            {
                
return nodeIter.Current.Value;
            }
            
else
            {
                
return null;
            }
        }
        
catch (Exception exception)
        {
            logger.Error(exception.Message, exception);
            
return null;
        }
    }

 

调用时:


//取得需要tab化的元数据Dictionary <类型,要表现的数据>
Dictionary<stringstring> containerList = GetInfor();
List
<Container> pages = new List<Container>();

foreach(string key in containerList )
{
     Container container 
= ContainerFactory(key, containerList[key]);
     
if(!pages.Contains(container))
     {
         pages.add(container); 
     } 
}

posted @ 2009-05-22 11:21  Apolloge  阅读(397)  评论(0编辑  收藏  举报