用反射动态创建对象,类型无法转换的困惑
企图:从XML读出节点并动态创建形成对象。
参考:http://www.cnblogs.com/Arlen/archive/2007/05/30/765506.html
工厂中的代码:
public class PublicSoftwareConfigFactory
{
protected Hashtable item = new Hashtable();
public IPublicSoftwareConfig this[PublicSoftwareConfigType type]
{
get
{
if(item.ContainsKey(type.ToString()))
return (IPublicSoftwareConfig)item[type.ToString()];
else
return null;
}
}
public PublicSoftwareConfigFactory(string srcXML)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(srcXML);
XmlNode root = doc.DocumentElement;
//从XML中提取对象
foreach(PublicSoftwareConfigType softwareType in Enum.GetValues(typeof(PublicSoftwareConfigType)))
{
XmlNode softwareNode = root.SelectSingleNode(softwareType.ToString().ToLower());
if(softwareNode == null)
continue;
Assembly assembly = Assembly.LoadFrom(@"E:\webApp\Helper\arlenliu_ConfigureProj_5_int\Dsecu_Moniter_VOB\Configure\ConfigEntity\bin\Debug\Tencent.Itil.Config.ConfigEntity.dll");
Type softwareClass = assembly.GetType("Tencent.Itil.Config.ConfigEntity.PublicSoftwareConfig." + softwareType.ToString());
//object softwareObj = Activator.CreateInstance(softwareClass);
object softwareObj = assembly.CreateInstance(softwareClass.FullName);
PropertyInfo[] propArr = softwareClass.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
for(int i=0;i<propArr.Length;i++)
{
XmlNode propNode = softwareNode.SelectSingleNode(propArr[i].Name.ToLower());
propArr[i].SetValue(softwareObj,propNode.InnerText,null);
}
if(!item.ContainsKey(softwareType.ToString()))
item.Add(softwareType.ToString(),softwareObj);
}
}
}
{
protected Hashtable item = new Hashtable();
public IPublicSoftwareConfig this[PublicSoftwareConfigType type]
{
get
{
if(item.ContainsKey(type.ToString()))
return (IPublicSoftwareConfig)item[type.ToString()];
else
return null;
}
}
public PublicSoftwareConfigFactory(string srcXML)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(srcXML);
XmlNode root = doc.DocumentElement;
//从XML中提取对象
foreach(PublicSoftwareConfigType softwareType in Enum.GetValues(typeof(PublicSoftwareConfigType)))
{
XmlNode softwareNode = root.SelectSingleNode(softwareType.ToString().ToLower());
if(softwareNode == null)
continue;
Assembly assembly = Assembly.LoadFrom(@"E:\webApp\Helper\arlenliu_ConfigureProj_5_int\Dsecu_Moniter_VOB\Configure\ConfigEntity\bin\Debug\Tencent.Itil.Config.ConfigEntity.dll");
Type softwareClass = assembly.GetType("Tencent.Itil.Config.ConfigEntity.PublicSoftwareConfig." + softwareType.ToString());
//object softwareObj = Activator.CreateInstance(softwareClass);
object softwareObj = assembly.CreateInstance(softwareClass.FullName);
PropertyInfo[] propArr = softwareClass.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
for(int i=0;i<propArr.Length;i++)
{
XmlNode propNode = softwareNode.SelectSingleNode(propArr[i].Name.ToLower());
propArr[i].SetValue(softwareObj,propNode.InnerText,null);
}
if(!item.ContainsKey(softwareType.ToString()))
item.Add(softwareType.ToString(),softwareObj);
}
}
}
业务逻辑:
public static void ModifyProcessForPublicSoftwareConfig(string Soruce, string Operator, string DeivceId, string SoftwareXmlStr)
{
//根据软件配置信息XML提取公用软件配置类
PublicSoftwareConfigFactory softwareFactory = new PublicSoftwareConfigFactory(SoftwareXmlStr);
IPublicSoftwareConfig obj = softwareFactory[PublicSoftwareConfigType.Kernel];
Kernel kernel = (Kernel)obj;
}
此段中的Kernel kernel = (Kernel)obj;出错,提示无法转换。{
//根据软件配置信息XML提取公用软件配置类
PublicSoftwareConfigFactory softwareFactory = new PublicSoftwareConfigFactory(SoftwareXmlStr);
IPublicSoftwareConfig obj = softwareFactory[PublicSoftwareConfigType.Kernel];
Kernel kernel = (Kernel)obj;
}
该IPublicSoftwareConfig则是在另一个DLL中定义,而Entity中的所有实体类都继承自它,只有这样才能转换成IPublicSoftwareConfig,但是最终还是不能转换成各实体对象。
有个解决办法:将该接口可能的所有子类的属性都在接口中声明。(很明显,这个办法是很不科学的。)
最后用反序列化解决该问题。
凡事不能太钻牛角尖。