C#通用XML阅读器代码

时间:2015-08-17 15:08:41

标签: c# linq generics lambda

我有一个程序,它解析三个不同的CrystalReport XML文件(类似的结构,但不同的后代级别),然后将值填充到一个类中。

以下是第一个例子:

    public static List<VyplatnePasky> DeserialzieRozuctovanieMzdy(ref List<VyplatnePasky> _pasky, string sPath)
    {
        XDocument document = XDocument.Load(sPath);
        var formattedAreaPairReport = from d in document.Descendants("FormattedReport".AddNamespace())
                                                        .Descendants("FormattedAreaPair".AddNamespace())
                                                        .Descendants("FormattedAreaPair".AddNamespace())
                                      select d.Element("FormattedAreaPair".AddNamespace());

        if (formattedAreaPairReport.Count() == 0)
        {
            //empty;
            InsertErrorMessage("<formattedAreaPairReport> contains no data! No Data to parse from.", "DeserialzieRozuctovanieMzdy");
            return _pasky;
        }

        //check if any sequence contains any matching elements
        var GotElements = formattedAreaPairReport.Elements("FormattedAreaPair".AddNamespace()).Where(n=>n.Attribute("Level").Value == "3" && n.Attribute("Type").Value == "Group");
        if (GotElements == null)
        {
            InsertErrorMessage("There are no matching elements under <formattedAreaPairReport>.", "DeserialzieRozuctovanieMzdy");
            return _pasky;
        }

        foreach (XElement xElement in GotElements)
        {
            RozuctovanieMzda_Values(xElement, ref _pasky);
        }

        return _pasky;
    }

这是第二个(第二个XML文档解析器):

    public static List<VyplatnePasky> DeserializeVyplatnePasky(string sPath)
    {
        List<VyplatnePasky> _pasky = new List<VyplatnePasky>();

        XDocument document = XDocument.Load(sPath);
        var formattedAreaPairReport = from d in document.Descendants("FormattedReport".AddNamespace())
                                      select d.Element("FormattedAreaPair".AddNamespace());

        if (formattedAreaPairReport.Count() == 0)
        {
            //empty;
            InsertErrorMessage("<formattedAreaPairReport> contains no data! No Data to parse from.", "DeserializeVyplatnePasky");
        }
        else
        {
            //sequence contains data
            foreach (XElement xElement in formattedAreaPairReport.Elements("FormattedAreaPair".AddNamespace()))
            {
                VyplatnePasky _paska = new VyplatnePasky();
                VyplatnePasky_Items(xElement, ref _paska);

                _pasky.Add(_paska);
            }
        }
        return _pasky;
    }

从上面的代码中可以看出,所有三种XML解析方法看起来几乎相同;主要区别在于我在后代的深度。的 formattedAreaPairReport

我想做的是通过创建可以由所有三种方法使用的Generic void来使这些代码更专业和可重用。

我正在考虑创建多个Delegates,我将传递我的lambda命令,例如:

            var formattedAreaPairReport = ProcessFirstLevel(from d in document.Descendants("FormattedReport".AddNamespace())
                                      select d.Element("FormattedAreaPair".AddNamespace()));
然而,它只会成为一个很大的混乱空白。

问题是 - 这实际上是可行/值得做的吗?你能帮忙吗?

1 个答案:

答案 0 :(得分:1)

您可以使用一些DRY技术稍微clean coding代码。尝试做这样的事情:

public static List<VyplatnePasky> DeserialzieRozuctovanieMzdy(ref List<VyplatnePasky> _pasky, string sPath)
{
    var formattedAreaPairReport =
    tryToGetItemsFromDocument
    (
        sPath,
        document=>from d in document.Descendants("FormattedReport".AddNamespace())
                  .Descendants("FormattedAreaPair".AddNamespace())
                  .Descendants("FormattedAreaPair".AddNamespace())
                  select d.Element("FormattedAreaPair".AddNamespace()),
        "DeserialzieRozuctovanieMzdy"
    );

    addItemsToVyplatnePasky(formattedAreaPairReport, ref _pasky);
    return _pasky;
}

public static List<VyplatnePasky> DeserializeVyplatnePasky(string sPath)
{
    List<VyplatnePasky> _pasky = new List<VyplatnePasky>();

    var formattedAreaPairReport =
    tryToGetItemsFromDocument
    (
        sPath,
        document=>from d in document.Descendants("FormattedReport".AddNamespace())
                  select d.Element("FormattedAreaPair".AddNamespace()),
        "DeserializeVyplatnePasky"
    );
    addItemsToVyplatnePasky2(formattedAreaPairReport, _pasky);
    return _pasky;
}

private static void addItemsToVyplatnePasky(IEnumerable<XElement> formattedAreaPairReport, ref List<VyplatnePasky> _pasky)
{
    if (formattedAreaPairReport.Count() > 0)
    {
        //check if any sequence contains any matching elements
        var GotElements = formattedAreaPairReport.Elements("FormattedAreaPair".AddNamespace()).Where(n=>n.Attribute("Level").Value == "3" && n.Attribute("Type").Value == "Group");
        if (GotElements == null)
        {
            InsertErrorMessage("There are no matching elements under <formattedAreaPairReport>.", "DeserialzieRozuctovanieMzdy");
            return;
        }

        foreach (XElement xElement in GotElements)
        {
            RozuctovanieMzda_Values(xElement, ref _pasky);
        }
    }

}

private static void addItemsToVyplatnePasky2(IEnumerable<XElement> formattedAreaPairReport, List<VyplatnePasky> _pasky)
{
    foreach (XElement xElement in formattedAreaPairReport.Elements("FormattedAreaPair".AddNamespace()))
    {
        VyplatnePasky _paska = new VyplatnePasky();
        VyplatnePasky_Items(xElement, ref _paska);

        _pasky.Add(_paska);
    }
}

private static IEnumerable<XElement> tryToGetItemsFromDocument(string sPath, Func<XDocument, IEnumerable<XElement>> query, string name)
{
    XDocument document = XDocument.Load(sPath);
    var report = query(document);
    if (report.Count() == 0)
    {
        //empty;
        InsertErrorMessage("<formattedAreaPairReport> contains no data! No Data to parse from.", name);
    }
    return report;
}

基本上,您可以继续分解代码,然后查找要清理的重复习语。泛型可能会或可能不会作为清理的一部分发挥作用。此外,您可能希望为方法提供比我更好的名称,因为我不熟悉此代码中使用的本机语言。 : - )