2011-01-06 25 views
1

我有一些存儲在表中的XML。我知道它應該反序列化到什麼對象,但我有很多類型的對象。泛型問題。我只是不理解如何製作一個通用的方法

所以,我有這個代碼,它的工作原理,但它是非常具體的1類型的對象。我想讓它通用來接受多種類型的對象之一。

Type _type = typeof(ReynoldsRCI.Services.rey_SvcApptView) 

XmlSerializer ser = new XmlSerializer(_type); 
object sck; 

using (StringReader reader = new StringReader(_msg.RawText)) 
{ 
    using (XmlTextReader xreader = new XmlTextReader(reader)) 
    { 
     sck = ser.Deserialize(xreader); 
    } 
} 

不過,我很想有一個1行的方法調用,我將它傳遞對象和文本的類型,它會反序列化,並將其返回給調用者使用。但就泛型而言,我完全是個白癡,所以我的代碼甚至沒有編譯。

public T DoStuff<T>(T _type, string RawText) 
{ 
    // Doesn't like this line. Error "The best overloaded method match for 'System.Xml.Serialization.XmlSerializer.XmlSerializer(System.Type)' has some invalid arguments" 
    XmlSerializer ser = new XmlSerializer(_type); 
    object retObj; 

    using (StringReader reader = new StringReader(RawText)) 
    { 
     using (XmlTextReader xreader = new XmlTextReader(reader)) 
     { 
     retObj = ser.Deserialize(xreader); 
     } 
    } 

    // Doesn't like this line, either "The type or namespace name '_type' could not be found" 
    return (_type)retObj; 
} 

對於泛型,我顯然缺少一些基本的東西,而且我無法將它拼湊在一起。有人可以用快速指針幫助我嗎?

+2

嘗試返回(T)retObj; – 2011-01-06 16:20:10

回答

13

要獲得類型T,您需要說typeof(T)。在您的方法結束時,要將retObj轉換爲T的實例,您必須說(T)retObj。因此

public T DoStuff<T>(string RawText) { 
    XmlSerializer ser = new XmlSerializer(typeof(T)); 
    // details elided 
    return (T)retObj; 
} 

的一點是,T正在播放的int,或string,或Foo或任何作用。也就是說,它是一個類型的名稱,而不是System.Type的實例。因此,您可以像使用其他類型的名稱一樣使用它。所以

new XmlSerializer(typeof(T)); 

類似於

new XmlSerializer(typeof(Foo)); 

return (T)retObj; 

類似於

return (Foo)retObj; 

思考的T作爲具體類型的佔位符。這裏的關鍵是要了解Footypeof(Foo)(或者說略有不同,類型如FooSystem.Type的實例,如typeof(Foo))之間的差異。

+0

XmlSerializer沒有基於泛型的方法,我現在不得不這樣做幾次,這很煩人 – 2011-01-06 16:24:17

+0

@Chris S:你可以編寫自己的工廠,在瞬間處理問題。這裏有一個開始:`class XmlSerializerFactory {public XmlSerializer CreateXmlSerializer (){return new XmlSerializer(typeof(T)); }}。用法:var factory = new XmlSerializerFactory(); XmlSerializer serializer = factory.CreateXmlSerializer ();`。 – jason 2011-01-06 16:26:10

+0

好的,是的,我是個白癡。我不需要傳入該類型,因爲我在調用它時指定了它。感謝您對語法的幫助。 – Matt 2011-01-06 17:04:18

2

您正在混合泛型類型參數和「正常」參數。

public T DoStuff<T>(string RawText) 
{ 
    XmlSerializer ser = new XmlSerializer(typeof(T)); 
    object retObj; 

    using (StringReader reader = new StringReader(RawText)) 
    { 
     using (XmlTextReader xreader = new XmlTextReader(reader)) 
     { 
      retObj = ser.Deserialize(xreader); 
     } 
    } 

    return (T)retObj; 
} 

請注意,是沒有辦法的編譯器可以可能推斷類型參數,所以你必須使用它作爲

string xml = ...; 
Foo foo = DoStuff<Foo>(xml); 

在另一方面:

  1. 考慮將方法重命名爲XmlDeserialize或類似的。
  2. 考慮將此設置爲string的擴展方法。
0

已經有一個很好的答案,但我已經寫了這個給你,所以我要添加它。我使用LinqPad寫它,所以Dump()是Console.Writeline()的縮寫。

void Main() 
{ 
    Testo testo = new Testo { First = "Phillip" }; 
    var abc = Serialize<Testo>(testo); 
    abc.ToString().Dump(); 
} 

public XDocument Serialize<T>(T obj) 
{ 
    var builder = new System.Text.StringBuilder(); 
    var settings = new XmlWriterSettings 
         { 
          Encoding = System.Text.Encoding.UTF8, 
          Indent = true, 
          IndentChars = ("\t"), 
          OmitXmlDeclaration = false 
         }; 

    var serializer = new XmlSerializer(typeof(T)); 

    using (var writer = XmlWriter.Create(builder, settings)) 
    { 
     serializer.Serialize(writer, obj); 
    } 

    var xml = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), XElement.Parse(builder.ToString())); 

    return xml; 
} 

public class Testo 
{ 
    public string First; 
} 
相關問題