2010-06-01 13 views
8

List<T> üzere bir akış (veya başka bir türü) serisini çalışılıyor yanılma ile başarısız am: Bu başarısızDeserialize Akış <T> veya başka bir türü Listeye

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); 
} 

Ama Bu çalışır:

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

ya:

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

Bunu döküm yapmadan yapmak mümkün mü, ör. (List<MyStruct>)stream.Deserialize()?

Güncelleme: hatayla stream.Deserialize<List<MyClass.MyStruct>>() sonuçları kullanarak
:

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() 

Güncelleme 2 (örnek konsol uygulaması) - yine

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(); 
    } 
} 
ondan okumak için, dosya oluşturmak için bir kez çalıştırmak

cevap

8

Uzatma yönteminizi şu şekilde çağırıyorsunuz:

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

Bu durumda, derleyici, Deserialize için T değerini belirleyemez (yöntem arama sonucunun atandığı değişkene bakmaz).

Yani açıkça tür bağımsız değişkeni belirtmek gerekir:

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

Bu çalışır:

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

@Sam: Seri hale getirme yönteminizde bir hata var. 'O' nesnesi yerine typeof (T) 'yi (bir RuntimeType olan) serileştiriyorsunuz! – dtb

+0

[Serializable], sadece örneklemeyi koymayı unutmuştum ... hata, serileştirme yerine serileştirmekti (atılmadığı için istisna olmadı diye düşünmedim) – SamWM

+0

@dtb: Ben de aynı sorunla karşılaştım BinaryFormatter'ım, işaret ettiğin için teşekkürler. XmlSerializer kurucuda typeof() kullandığı için gözden kaçırmak kolaydır. – angularsen

1
Sen jenerik türünü belirtmek için orijinal jenerik yöntem, sadece var kullanabilirsiniz

açıkça böyle ...

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

Listenin türünü değil, gerçek listeyi serileştiriyorsunuz. Olmalıdır:

bin.Serialize(stream, o) 

Ayrıca, doğru serialize için Serializable olarak MyStruct işaretlemek zorunda kalacaktır.

İlgili konular