我从不同的客户那里获得了多个 XSD,我需要以符合他们提供的 XSD 的 XML 格式向他们提供数据。我已经编写了一个代码来使用 codedom、System.Reflection 和 codeprovider 从 XSD 动态创建和编译一个类。现在我的计划是通过多个查询从数据库中获取数据,并将字段映射到创建的动态类的属性并对其进行序列化。我正在寻找一种映射这些字段的通用方法,该方法可用于任何类型的 xsd,并且只需映射它将序列化并提供 XML 文件的字段。至于查询,我将它们放在配置文件中。通用解决方案可行吗?关于如何去做的任何想法或指示?
问问题
2238 次
2 回答
1
我能够解决这个问题。以下是我使用的步骤: 我首先使用反射和 codedom.compiler 从 xsd 创建了一个内存运行时程序集,并带有可序列化的属性。使用反射,我在该程序集中创建了类的实例,并从我从数据库中获得的数据中分配了属性。这个类我转发给另一个序列化的方法接受一个对象并将其序列化为 xml。
至于映射,我确保数据库列名称需要与 xml 属性名称匹配,并且我能够映射和调用它们。
这是片段:
object fxClass = myAssembly.CreateInstance(cls.FullName);
Type t = fxClass.GetType();
var arrRates = Array.CreateInstance(t, tab.Rows.Count);
int i =0;
foreach (DataRow dr in tab.Rows)
{
fxClass = myAssembly.CreateInstance(cls.FullName);
PropertyInfo[] fxRateProperties = t.GetProperties();
foreach (PropertyInfo prop in fxRateProperties)
{
string rowVal = dr[prop.Name].ToString();
if (prop.PropertyType == typeof(DateTime))
{
prop.SetValue(fxClass, util.convertToDate(rowVal), null);
}
else if (prop.PropertyType == typeof(bool))
{
prop.SetValue(fxClass, util.convertToBoolean(rowVal), null);
}
else if (prop.PropertyType == typeof(decimal))
{
prop.SetValue(fxClass, util.convertToDecimal(rowVal), null);
}
else prop.SetValue(fxClass, rowVal, null);
}
arrRates.SetValue(fxClass,i);
i++;
}
myClass.GetType().GetProperty("ForexRates").SetValue(myClass, arrRates, null);
然后将 myClass 对象传递给接受对象类型的序列化方法,就是这样
public void serializeXML(object portfolio, string xmlPath)
{
XmlSerializer serial = new XmlSerializer(portfolio.GetType());
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
try
{
using (FileStream fs = new FileStream(xmlPath, FileMode.Create, FileAccess.Write))
{
using (XmlTextWriter tw = new XmlTextWriter(fs, Encoding.UTF8))
{
tw.Formatting = Formatting.Indented;
serial.Serialize(tw, portfolio, ns);
}
}
}
}
为此,现在我计划添加一个 UI 片段,其中“ForexRates”之类的映射保存在数据库中,然后它将打开任何 xsd 类型。
非常感谢您的回复。
于 2012-03-15T18:25:04.077 回答
0
您不能序列化动态创建的类——至少,不是正常的方式。即使您找到了附加Serializable
属性的方法,它也不会产生任何影响:不会生成序列化程序集。
从理论上讲,您可以发出一个全新的类并在运行时 sgen 它,但这绝对是一件痛苦的事。如果您要这样做,我会推荐 Mono.Cecil 而不是 .NET Framework 的默认 IL 发射器。
于 2012-02-10T04:12:59.227 回答