2016-03-30 16 views
0

DataContractSerializer kullanarak soyut tipli Sözlük serileştirmenin bir yolu var mı? Örneğin

[DataContract] 
public abstract class BaseClass 
{ 
    public abstract string id { get; set; } 
} 

[DataContract(Name = "class1")] 
public class concreteClass1 : BaseClass 
{ 
    public concreteClass1() { } 

    [DataMember] 
    public override string id { get; set; } 

    [DataMember] 
    public string prop1 { get; set; } 

    [DataMember] 
    public string prop2 { get; set; } 

} 

[DataContract(Name = "class2")] 
public class concreteClass2 : BaseClass 
{ 
    public concreteClass2() { } 

    [DataMember] 
    public override string id { get; set; } 

    [DataMember] 
    public string prop1 { get; set; } 

    [DataMember] 
    public string prop2 { get; set; } 

} 

Ben bu hatayı alıyorum bu

static public void Main(string[] args){ 

    Dictionary<string, BaseClass> items = new Dictionary<string, BaseClass>(); 
    items.Add("1", new concreteClass1() { id = "1", prop1 = "blah1" }); 
    items.Add("11", new concreteClass1() { id = "11", prop1 = "blah11" }); 

    var serializer = new DataContractSerializer(items.GetType()); 
    string xmlString = string.Empty; 
    using (var sw = new StringWriter()) 
    { 
     using (var writer = new XmlTextWriter(sw)) 
     { 
      writer.Formatting = System.Xml.Formatting.Indented; 
      serializer.WriteObject(writer, items); 
      writer.Flush(); 
      xmlString = sw.ToString(); 
     } 
    } 

} 

gibi somut sınıfların birini içeren bir sözlük seri hale getirilmeye açmaya

Tipi 'writeObject

çalışırken ConsoleTest .Program + Base 'serileştirilemez. DataContractAttribute özniteliğiyle işaretini işaretleyin ve DataMemberAttribute özniteliği ile serileştirilmesini istediğiniz tüm üyelerini işaretleyin. Tür bir koleksiyon ise, CollectionDataContractAttribute ile işaretlemeyi düşünün. Desteklenen diğer türler için Microsoft .NET Framework belgelerine bakın.

Bunu çözmenin bir yolu var mı?

DÜZENLEME: ....

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Runtime.Serialization; 
using System.Xml; 

sınıfları Ayrıca temel sınıf üzerinde KnownType kullanarak denedik ama kullanan ...

[DataContract] 
    [KnownType(typeof(concreteClass1))] 
    [KnownType(typeof(concreteClass2))] 
    public abstract class BaseClass 
    { 
     public abstract string id { get; set; } 
    } 
+0

Aşağıdaki kod satırında TL nedir ?: serializer.WriteObject (yazar, TL) ; – iCode

+0

@iCode yazım hatası – erotavlas

+0

Bunu açıklığa kavuşturmak için gerekli olduğunu düşündüm. Kodunuzu bir test projesinde kopyaladım ... Konsola xmlString yazmak için bir kod satırı ekledim ve benim için çalıştı. XML'i buraya yapıştırmak istemedim ama işe yaradı. Kullanmaya çalışırken (var sw = new StringWriter()) kod bloğunu sarmalamayı deneyin ve istisna ayrıntılarını görüntüleyin. – iCode

cevap

1

bu deneyin

işe yaramadı ...

[DataContract] 
[KnownType(typeof(concreteClass1))] 
[KnownType(typeof(concreteClass2))] 
public abstract class BaseClass 
{ 
    [DataMember] 
    public abstract string id { get; set; } 
} 

[DataContract(Name = "class1")] 
public class concreteClass1 : BaseClass 
{ 
    public concreteClass1() { } 

    [DataMember] 
    public override string id { get; set; } 

    [DataMember] 
    public string prop1 { get; set; } 

    [DataMember] 
    public string prop2 { get; set; } 

} 

[DataContract(Name = "class2")] 
public class concreteClass2 : BaseClass 
{ 
    public concreteClass2() { } 

    [DataMember] 
    public override string id { get; set; } 

    [DataMember] 
    public string prop1 { get; set; } 

    [DataMember] 
    public string prop2 { get; set; } 

} 

code ....

static void Main(string[] args) 
    { 
     Dictionary<string, BaseClass> items = new Dictionary<string, BaseClass>(); 
     items.Add("1", new concreteClass1() { id = "1", prop1 = "blah1" }); 
     items.Add("11", new concreteClass1() { id = "11", prop1 = "blah11" }); 
     // this should work too.... 
     items.Add("999", new concreteClass2() { id = "999", prop1 = "blah999" }); 
     items.Add("888", new concreteClass2() { id = "888", prop1 = "blah888" }); 

     //Serialize(items); 

     var serializer = new DataContractSerializer(items.GetType()); 
     string xmlString = string.Empty; 
     try 
     { 
      using (var sw = new StringWriter()) 
      { 
       using (var writer = new XmlTextWriter(sw)) 
       { 
        writer.Formatting = System.Xml.Formatting.Indented; 
        serializer.WriteObject(writer, items); 
        writer.Flush(); 
        xmlString = sw.ToString(); 
       } 
      } 
     } 
     catch (Exception) 
     { 

      throw; 
     } 
    } 

///////////////////// GÜNCELLEME /////////////////// bir bonus biraz itibariyle //

burada tefrika ve genel bir nesne deserialise edecek iki işlev .....

 public static void Serialize<T>(T data) 
     { 
      try // try to serialize the collection to a file 
      { 
       using (Stream stream = File.Open("data.xml", FileMode.Create)) 
       { 
        // create DataContractSerializer 
        DataContractSerializer serializer = new DataContractSerializer(typeof (T)); 
        // serialize the collection (EmployeeList1) to file (stream) 
        serializer.WriteObject(stream, data); 
       } 
      } 
      catch (IOException) 
      { 
      } 
     } 

     public static T Deserialize<T>() where T : new() 
     { 
      // Create an instance of T 
      T ReturnListOfT = CreateInstance<T>(); 

      // Try to Deserialize from file stream 
      try 
      { 
       using (Stream stream = File.Open("data.xml", FileMode.Open)) 
       { 
        // create DataContractSerializer 
        DataContractSerializer serializer = new DataContractSerializer(typeof (T)); 
        // deserialize the collection (Employee) from file (stream) 
        ReturnListOfT = (T)serializer.ReadObject(stream); 
       } 
      } 
      catch (IOException) 
      { 
      } 

      return (T)ReturnListOfT; 
     } 

     // function to create instance of T 
     public static T CreateInstance<T>() where T : new() 
     { 
      return (T)Activator.CreateInstance(typeof(T)); 
     } 

yerine vardır (hissetmiyorum henüz benim 25 puan kulaklı) XML'i manuel olarak değiştirmek zorunda olduğunuzda, varolan sınıflarınızı kullanarak nesneyi ('data.xml' örneğindeki bir dosyadan) kaldırabilir ve kullanıcıya izin vermek için bir Kullanıcı Arayüzü oluşturabilirsiniz. object \ sınıflarının özelliklerini değiştirmek ve sonra değiştirilen nesneyi bir dosyaya geri döndürmek üzere yeniden kaydetme .....

+0

boyunca oldu Ama id soyut bir özellik, Uygulamam gerekiyor – erotavlas

+0

Benim hatam, 'id' serisini (bir dizgeye) serileştiririm Bir dosyaya serileştiriyordum ve orada göremedim, tekrar kontrol edeceğim .. siz doğru olanları sınıflarım ve cevabımı değiştirdim. ... – Monty

+0

Ayrıca NetDataContractSerializer çalıştı ve daha iyi çalışıyor - aslında türleri serileştirir Doğru, ancak XML çıkışı daha karmaşık ve daha az kullanıcı dostu (el ile değişiklik yapmanız gerektiğinde) – erotavlas

İlgili konular