说说C#下的动态可配置的扩展
前几天给一个系统做了一个小模块,类似于一个tab组件,和主程序关系不大。但是tab的page页需要根据实际情况进行扩展,同时每个page页的表现都不一样(根据具体需求变动),并且希望这个扩展可以通过外部配置文件配置(类似于Plusin)。
开始没有什么头绪,后来想到扩展的部分可以通过继承的方式实现,在基类中定义输出表现的虚函数,然后在扩展的子类中实现该虚方法,实现自己的表现。通过这种“多态”,实现了扩展的要求。对于新的扩展机能,只需要从该基类继承,实现相应的虚方法,就达到了扩展的目的,而且一点也不影响既存的技能。
对于可配置方面,想通过反射的机制来实现,将扩展的类名声明到配置文件中,使用C#的反射机制,加载具体的子类,以实现可配置的要求。
下面用代码简单的说明一下:
基类的定义:
{
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 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 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 "未知";
}
}
}
......
配置文件:
<Configuration>
<!--Containers-->
<Containers>
<!--HardwareStatus-->
<Container>
<Type>HardwareStatus</Type>
<ContainerName>硬件状态</ContainerName>
<Index>0</Index>
<Class>Serialize.TabContainer.HardwareStatusContainer</Class>
<!--Memory-->
<Container>
<Type>Memory</Type>
<ContainerName>内存</ContainerName>
<Index>1</Index>
<Class>Serialize.TabContainer.MemorySizeContainer </Class>
</Container>
</Configuration>
反射加载:
{
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<string, string> 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);
}
}