我有多种方法从XML读取数据,格式如下:
<?xml version = "1.0" encoding="UTF-8" standalone="yes"?>
<document>
<employee>
<name>
<lastname>Sample</lastname>
<firstname>Test</firstname>
</name>
<professionalDetails>
<hiredate>October 15, 2016</hiredate>
<designation>Clerk</designation>
</professionalDetails>
<projects>
<project>
<product>Printer</product>
<id>111</id>
<price>$111.00</price>
</project>
<project>
<product>Laptop</product>
<id>222</id>
<price>$989.00</price>
</project>
</projects>
</employee>
</document>
要阅读上述数据,我有以下方法及其各自的类。
方法:
private static NameDetails GetsNameDetails(XNode content)
{
var element = content.XPathSelectElement("document/employee/name");
return new NameDetails
{
FirstName = element.GetElementAsString("firstName"),
LastName = element.GetElementAsString("lastName")
};
}
private static ProfessionalDetails GetsProfessionalDetailsDetails(XNode content)
{
var element = content.XPathSelectElement("document/employee/professionalDetails");
return new ProfessionalDetails
{
HireDate = element.GetElementAsString("hiredate"),
Designation = element.GetElementAsString("designation")
};
}
private static Projects GetsProjectDetails(XNode content)
{
var element = content.XPathSelectElement("document/employee/projects/project");
return new Projects
{
Id = element.GetElementAsString("id"),
Price = element.GetElementAsString("price"),
Product = element.GetElementAsString("product")
};
}
}
internal class Projects
{
public int Id { get; set; }
public string Product { get; set; }
public string Price { get; set; }
}
internal class ProfessionalDetails
{
public DateTime HireDate { get; set; }
public string Designation { get; set; }
}
internal class NameDetails
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
两种方法的基础逻辑相同。初始化类型是唯一被改变的东西。方法的返回值和要初始化的属性/字段会发生变化,但参数保持不变。
如何为以下方法使用一个通用方法并确定在运行时初始化的类型?
答案 0 :(得分:1)
你可以这样写:
lst = [1,2,3,3,4,4,5,6]
lst2 = []
for i in lst:
if i not in lst2:
lst2.append(i)
print(lst2)
[1, 2, 3, 4, 5, 6]
或者,您可以使用XML库,只需定义如何通过属性和映射填充字段。
答案 1 :(得分:0)
您可以添加泛型类型,然后根据类型决定您要如何解析节点:
private static T GetsDetails<T>(XNode content)
{
if(typeof(T) == typeof(ProjectDetails)){
var element = content.XPathSelectElement("document/employee/projects/project");
return (T)new Projects
{
Id = element.GetElementAsString("id"),
Price = element.GetElementAsString("price"),
Product = element.GetElementAsString("product")
};
}
else if(typeof(T) == typeof(ProfessionalDetails){ ... }
else if (...) {...}
}
我不会推荐这种方法:你仍然需要进行类型检查而且你获得的收益很少。您最初的实施要简单得多。
答案 2 :(得分:0)
您可以创建一个属性来确定应该使用哪个XPath表达式。例如:
[XPathSelector("document/employee/projects/project")]
internal class Projects
{
public int Id { get; set; }
public string Product { get; set; }
public string Price { get; set; }
}
然后你可以通过反射使用它(代码未经测试,此处没有c#编译器):
private static T GetNode<T>(XNode content)
: where T : new()
{
var selector = typeof(T).GetCustomProperty<XPathSelector>();
var element = content.XPathSelectElement(selector.XPathSelector);
var ret = new T();
foreach (var child in element.Elements) {
var property = typeof(T).GetProperties().Single(p => p.Name.ToLower() == child.Name.ToLower());
property.SetValue(ret, child.GetElementAsString(child.Name));
}
return ret;
}