2010-06-01 12 views
8

List<T> को एक धारा (या किसी भी अन्य प्रकार) deserialize करने का प्रयास और त्रुटि के साथ विफल रहा:deserialize स्ट्रीम <T> या किसी भी अन्य प्रकार सूची में

The type arguments for method Foo.Deserialize<T>(System.IO.Stream) cannot be inferred from the usage. Try specifying the type arguments explicitly.

यह विफल रहता है:

public static T Deserialize<T>(this Stream stream) 
{ 
    BinaryFormatter bin = new BinaryFormatter(); 
    return (T)bin.Deserialize(stream); 
} 

लेकिन इस काम करता है:

public static List<MyClass.MyStruct> Deserialize(this Stream stream) 
{ 
    BinaryFormatter bin = new BinaryFormatter(); 
    return (List<MyClass.MyStruct>)bin.Deserialize(stream); 
} 

या:

public static object Deserialize(this Stream stream) 
{ 
    BinaryFormatter bin = new BinaryFormatter(); 
    return bin.Deserialize(stream); 
} 

क्या यह बिना कास्टिंग किए ऐसा करना संभव है, उदा। (List<MyStruct>)stream.Deserialize()?

अद्यतन:
का उपयोग stream.Deserialize<List<MyClass.MyStruct>>() परिणाम एक त्रुटि में:

System.InvalidCastException: Unable to cast object of type 'System.RuntimeType' 
to type 'System.Collections.Generic.List`1[MyClass+MyStruct]'. 
at StreamExtensions.Deserialize[T](Stream stream) 
at MyClass.RunSnippet() 

अद्यतन 2 (नमूना सांत्वना एप्लिकेशन) - फ़ाइल बनाने के लिए एक बार फिर से चलाएं इसे से

using System; 
using System.IO; 
using System.Collections.Generic; 
using System.Runtime.Serialization; 
using System.Runtime.Serialization.Formatters; 
using System.Runtime.Serialization.Formatters.Binary; 

public static class StreamExtensions 
{ 
    public static Stream Serialize<T>(this T o) where T : new() 
    { 
     Stream stream = new MemoryStream(); 
     BinaryFormatter bin = new BinaryFormatter(); 
     bin.Serialize(stream, typeof(T)); 
     return stream; 
    } 

    public static T Deserialize<T>(this Stream stream) where T : new() 
    { 
     BinaryFormatter bin = new BinaryFormatter(); 
     return (T)bin.Deserialize(stream); 
    } 

    public static void WriteTo(this Stream source, Stream destination) 
    { 
     byte[] buffer = new byte[32768]; 
     source.Position = 0; 
     if(source.Length < buffer.Length) buffer = new byte[source.Length]; 
     int read = 0; 
     while ((read = source.Read(buffer, 0, buffer.Length)) != 0) 
     { 
      destination.Write(buffer, 0, read); 
     } 
    } 
} 


public class MyClass 
{ 
    public struct MyStruct 
    { 
     public string StringData; 
     public MyStruct(string stringData) 
     { 
      this.StringData = stringData; 
     } 
    } 

    public static void Main() 
    { 
     // binary serialization 
     string filename_bin = "mydata.bin"; 
     List<MyStruct> l; 
     if(!File.Exists(filename_bin)) 
     { 
      Console.WriteLine("Serializing to disk"); 
      l = new List<MyStruct>(); 
      l.Add(new MyStruct("Hello")); 
      l.Add(new MyStruct("Goodbye")); 
      using (Stream stream = File.Open(filename_bin, FileMode.Create)) 
      { 
       Stream s = l.Serialize(); 
       s.WriteTo(stream); 
      } 
     } 
     else 
     { 
      Console.WriteLine("Deserializing from disk"); 
      try 
      { 
       using (Stream stream = File.Open(filename_bin, FileMode.Open)) 
       { 
        l = stream.Deserialize<List<MyStruct>>(); 
       } 
      } 
      catch(Exception ex) 
      { 
       l = new List<MyStruct>(); 
       Console.WriteLine(ex.ToString()); 
      } 
     } 

     foreach(MyStruct s in l) 
     { 
      Console.WriteLine(
       string.Format("StringData: {0}", 
        s.StringData 
       ) 
      ); 
     } 

     Console.ReadLine(); 
    } 
} 
पढ़ने के लिए

उत्तर

8

मुझे लगता है कि आप अपनी विस्तार विधि को इस तरह बुला रहे हैं:

List<MyStruct> result = mystream.Deserialize();  

इस मामले में, संकलक Deserialize के लिए T निर्धारित नहीं कर सकता है (यह विधि कॉल परिणाम को वैरिएबल को नहीं देखता है)।

तो आप स्पष्ट रूप से प्रकार तर्क निर्दिष्ट करने की आवश्यकता:

List<MyStruct> result = mystream.Deserialize<List<MyStruct>>(); 

यह काम करता है:

public static class StreamExtensions 
{ 
    public static void SerializeTo<T>(this T o, Stream stream) 
    { 
     new BinaryFormatter().Serialize(stream, o); // serialize o not typeof(T) 
    } 

    public static T Deserialize<T>(this Stream stream) 
    { 
     return (T)new BinaryFormatter().Deserialize(stream); 
    } 
} 

[Serializable] // mark type as serializable 
public struct MyStruct 
{ 
    public string StringData; 
    public MyStruct(string stringData) 
    { 
     this.StringData = stringData; 
    } 
} 

public static void Main() 
{ 
    MemoryStream stream = new MemoryStream(); 

    new List<MyStruct> { new MyStruct("Hello") }.SerializeTo(stream); 

    stream.Position = 0; 

    var mylist = stream.Deserialize<List<MyStruct>>(); // specify type argument 
} 
+3

@ सैम: आपके सीरियलize विधि में एक बग है। आप ऑब्जेक्ट 'ओ' के बजाय' टाइपोफ (टी) '(जो एक रनटाइम टाइप है) को क्रमबद्ध कर रहे हैं! – dtb

+0

था [Serializable], बस इसे नमूना में रखना भूल गया ... बग deserialization के बजाय serialization था (इसके बारे में नहीं सोचा था क्योंकि कोई अपवाद फेंक दिया गया था) – SamWM

+0

@ डीटीबी: मुझे एक ही समस्या थी मेरा बाइनरीफॉर्मेटर, इसे इंगित करने के लिए धन्यवाद। XmlSerializer कन्स्ट्रक्टर में टाइपऑफ() का उपयोग करता है क्योंकि यह अनदेखा करना आसान है। – angularsen

1

आप सामान्य प्रकार निर्दिष्ट करने के अपने मूल सामान्य विधि का उपयोग कर सकते हैं, तो आप सिर्फ है स्पष्ट रूप से ऐसा ...

stream.Deserialize<List<MyClass.MyStruct>>(); 
1

आप सूची के प्रकार को क्रमबद्ध कर रहे हैं न कि वास्तविक सूची। यह होना चाहिए:

bin.Serialize(stream, o) 

इसके अलावा, आप Serializable रूप MyStruct चिह्नित करने के लिए यह इसे सही ढंग से क्रमानुसार करने के लिए होगा।

संबंधित मुद्दे