【问题标题】:List<T> to XML string Extension Method [closed]List<T> 到 XML 字符串扩展方法 [关闭]
【发布时间】:2015-10-06 15:00:53
【问题描述】:

如何创建扩展方法来将我的 T 列表转换为 XML 字符串。 我的 T 对象的属性变成了 xml 标签,而属性的值变成了 xml 标签中的值。我的 T 对象具有简单的字符串属性,即没有集合或二维对象。也就是说,所有属性都是字符串、整数等,即一维……没有列表/数组作为属性。

【问题讨论】:

  • 闻起来像个面试题!
  • 扩展方法可能不是最好的选择;我会考虑一个类(由接口抽象)。这将允许您提供一个用于 XML 序列化的类和另一个用于 CSV 的类。我看到的扩展方法的问题是,它必须在静态类中实现......并且以某种方式应该是多态的功能不应该是静态的......只是我的两分钱。
  • 哈哈!不是。我计划通过 File.AppendAllText(".xml") 将我的列表对象转换为 xml 文件,方法是给它一个文件扩展名。我基本上将我的数据放在我的对象的一个​​级别维度中。我只需要看看是否有更简单的方法可以将我的所有转换代码删除为列表扩展方法但也许,我可以删除文件部分。也许只是一个 xml 输出。
  • this page上有Xml序列化的扩展方法
  • @stuartd 谢谢让我试试这个。

标签: c# xml list csv extension-methods


【解决方案1】:

如果你想转换例如这种列表:

List<int> Branches = new List<int>();
Branches.Add(1);
Branches.Add(2);
Branches.Add(3);

进入这个 XML:

<Branches>
    <branch id="1" />
    <branch id="2" />
    <branch id="3" />
</Branches>

您可以使用 LINQ 进行尝试:

List<int> Branches = new List<int>();
Branches.Add(1);
Branches.Add(2);
Branches.Add(3);

XElement xmlElements = new XElement("Branches", Branches.Select(i => new XElement("branch", new XAttribute("id", i))));
System.Console.Write(xmlElements);
System.Console.Read();

输出:

<Branches>
  <branch id="1" />
  <branch id="2" />
  <branch id="3" />
</Branches>

您需要包含using System.Xml.Linq; 命名空间。

编辑:要制作文件,您可以使用此方法

 public string ToXML<T>(T obj)
 {
    using (StringWriter stringWriter = new StringWriter(new StringBuilder()))
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        xmlSerializer.Serialize(stringWriter, obj);
        return stringWriter.ToString();
    }
 }

【讨论】:

  • 创建 XML 片段,而不是文件
  • @stuartd - XElement.Save(string fileName) 将负责创建文件。
  • 选项如果我不想使用属性,但元素?
  • @JeffJaffery 也许你可以看看这个msdn.microsoft.com/en-us/library/bb387083.aspx
  • @VERYNET 工作就像一个魅力。谢谢大家的回答。
【解决方案2】:

您所说的大致翻译为“序列化”,并且与大多数通用问题一样,这个问题已得到解决。该框架当然为您提供了一些用于 Xml 序列化的工具。

给定一个类:

public class TestClass
{
    public string Prop1 {get;set;}
    public string Prop2 {get;set; }
}

还有一个扩展方法:

public static class SerializationExtensions
{
    public static string ToXml<T>(this List<T> list)
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<T>)); 

        StringWriter stringWriter = new StringWriter(); 
        XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter); 

        xmlWriter.Formatting = Formatting.Indented; 
        xmlSerializer.Serialize(xmlWriter, list); 

        return stringWriter.ToString();     
    }
}

一个简单的演示生成xml

<?xml version="1.0" encoding="utf-16"?>
<ArrayOfTestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <TestClass>
    <Prop1>val1</Prop1>
    <Prop2>val2</Prop2>
  </TestClass>
  <TestClass>
    <Prop1>val1</Prop1>
    <Prop2>val2</Prop2>
  </TestClass>
  <TestClass>
    <Prop1>val1</Prop1>
    <Prop2>val2</Prop2>
  </TestClass>
</ArrayOfTestClass>

序列化为文件而不是字符串会很简单,但为了演示用法,输出为字符串更容易。

现场演示:http://rextester.com/AKIBNI2909

【讨论】:

  • 哇,谢谢! @Jamiec。我看到了我的问题中的缺陷,我应该只使用字符串并在其他地方执行文件 IO。
【解决方案3】:

创建扩展方法与常规方法没有太大区别。如果使用关键字“this”指定第一个参数(方法将扩展的对象),您只需将方法设为静态即可。剩下的只是计划反思。

    public static string GetXML<T>(this List<T> src)
    {
        // First, we have to determine the "Type" of the generic parameter.
        Type srcType = src.GetType();
        Type[] srcTypeGenArgs = srcType.GetGenericArguments();
        if (srcTypeGenArgs.Length != 1)
            throw new Exception("Only designed to work on classes with a single generic param.");
        Type genType = srcTypeGenArgs[0];

        // Get the properties for the generic Type "T".
        System.Reflection.PropertyInfo[] typeProps = genType.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.GetProperty);

        // Now, we loop through each item in the list and extract the property values.
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("<root>");
        for (int i = 0; i < src.Count; i++)
        {
            T listItem = src[i];
            for (int t = 0; t < typeProps.Length; t++)
            {
                object propVal = typeProps[t].GetValue(listItem, null); // Always pass "null" for the index param, if we're not dealing with some indexed type (like an array).
                string propValStr = (propVal != null ? propVal.ToString() : string.Empty);
                sb.AppendLine(string.Format("<{0}>{1}</{0}>", typeProps[t].Name, propValStr));
            }
        }
        sb.AppendLine("</root>");
        return sb.ToString();
    }

【讨论】:

  • 代码的整个第一位可以替换为var genType = typeof(T)
  • 嗯..我认为“typeof”不适用于通用参数。我想,我一直都是这样做的。很高兴知道。谢谢。
  • 感谢您的回答。真的很有帮助@MikeU
猜你喜欢
  • 1970-01-01
  • 2011-10-01
  • 1970-01-01
  • 2018-01-15
  • 1970-01-01
  • 1970-01-01
  • 2012-12-01
  • 2012-04-06
  • 1970-01-01
相关资源
最近更新 更多