如何使方法/ s泛型返回不同的类型,但接受相同类型的实例?

时间:2016-10-26 22:01:10

标签: c# asp.net .net xml generics

我有多种方法从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>

要阅读上述数据,我有以下方法及其各自的类。

  • 请注意,我有自己的&#34; GetElementAsString &#34;方法。请耐心等待我的实施。

方法:

    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; }
}

两种方法的基础逻辑相同。初始化类型是唯一被改变的东西。方法的返回值和要初始化的属性/字段会发生变化,但参数保持不变。

如何为以下方法使用一个通用方法并确定在运行时初始化的类型?

3 个答案:

答案 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;
}