2015-10-06 57 views
0

如何創建一個擴展方法來將我的List of T轉換爲XML字符串。 我的T對象的屬性成爲xml標記,並且該屬性的值成爲xml標記內的值。我的T對象具有簡單的字符串屬性,即沒有集合或二維對象。這是所有的屬性是字符串,INT等,即一維..沒有列表/數組作爲一個屬性。列表<T>到XML字符串擴展方法

+1

聞起來像面試問題! – DavidG

+0

擴展方法可能不是最好的選擇;我會考慮一個類,而不是由一個接口抽象出來。這將允許您爲XML序列化提供一個類,爲CSV提供另一個類。我用擴展方法看到的問題是,它必須在一個靜態類中實現......並且某些方面應該是多態的功能不應該是靜態的......僅僅是我的兩分錢。 – Matze

+0

哈哈!它不是。我打算通過給它一個文件擴展名,通過File.AppendAllText(「。xml」)將我的列表對象轉換爲一個xml文件。我基本上在我的對象中有一個維度的數據。我只需要查看是否有更簡單的方法將所有的convertion代碼刪除到列表擴展方法中但是也許我可以刪除文件部分。也許只是一個XML輸出。 – JeffJeffery

回答

2

如果你想例如這種列表的轉換:

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(); 
    } 
} 
+1

創建XML _fragment_,而不是文件 – stuartd

+1

@stuartd - 'XElement.Save (string fileName)'會照顧創建文件。 –

+0

選項如果我不想使用屬性,但元素? – JeffJeffery

0

創建擴展方法是不是一個普通的方法是非常不同的。如果使用關鍵字「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(); 
    } 
+0

你的代碼的整個第一位可以用'var genType = typeof(T)' – Jamiec

+0

替換嗯..我不認爲「typeof」對泛型params有效。我想,我一直在做很長的路。很高興知道。謝謝。 –

+0

感謝您的回答。真的很有幫助@MikeU – JeffJeffery

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

+0

哇謝謝你! @Jamiec。我發現我的問題存在缺陷,我應該只使用字符串並在別處執行文件IO。 – JeffJeffery