2013-05-21 1 views
1

У меня есть структура несколько, как перечисление, за исключением того, что имеет кучу способов:данных контракта Одно значение Структура

public struct ComponentIdentifier : IComparable 
{ 
    private long identifier; 

    ... 
} 

Я хочу это сериализовать такие, что <ComponentIdentifier/ComponentIdentifier> является это возможно?

Я хочу, чтобы это работало для xml и json.

Спасибо.

ответ

0

Есть несколько вариантов.

  1. Вариант 1 - Объявлять во всех родительских объектах ComponentIdentifier, которые обрабатывают Сериализации
  2. Вариант 2 - контракт Данные пользователя суррогатного
  3. Вариант 3 - Использовать Json.NET в JsonConverter

Недостатки

  1. Вариант 1 - Код, необходимый для всех классов, использующих ComponentIdentifier & идентификатор, сделанный public
  2. Вариант 2 - Вы не сможете десериализовать этот метод.
  3. Вариант 3 - не Microsoft библиотеки, может потребоваться настройка производительности

Я работаю через эту проблему сам, и я склоняюсь к опции # 3. Мне бы это понравилось, если бы Microsoft смогла сделать еще один оборот DataContractSerializer, чтобы сделать его немного более гибким, увы.

Вариант 1:

static void Main(string[] args) 
{ 
    var serializeMe = new Foo() { Id = new ComponentIdentifier() }; 
    var xml = Serialize(serializeMe); 
    Console.WriteLine(xml); 
    Console.ReadKey(); 
} 

[DataContract] 
public class Foo 
{ 
    [DataMember(Name = "Id")] 
    private string IdForSerialization 
    { 
     get { return Id.identifier.ToString(); } 
     set { Id = new ComponentIdentifier() {identifier = int.Parse(value)}; } 
    } 

    public ComponentIdentifier Id { get; set; } 
} 

[DataContract] 
public struct ComponentIdentifier 
{ 
    [DataMember] 
    public long identifier; 
} 

// thanks to http://stackoverflow.com/questions/5010191/using-datacontractserializer-to-serialize-but-cant-deserialize-back 
public static string Serialize(object obj) 
{   
    using (MemoryStream memoryStream = new MemoryStream()) 
    using (StreamReader reader = new StreamReader(memoryStream)) 
    { 
     DataContractSerializer serializer = new DataContractSerializer(obj.GetType()); 
     serializer.WriteObject(memoryStream, obj); 
     memoryStream.Position = 0; 
     return reader.ReadToEnd(); 
    } 
} 

Вариант 2:

static void Main(string[] args) 
{ 
    var serializeMe = new Foo() { Id = new ComponentIdentifier() }; 
    var xml = Serialize(serializeMe, new ComponentIdentifierSurrogate()); 
    Console.WriteLine(xml); 
    Console.ReadKey(); 
} 

[DataContract] 
public class Foo 
{ 
    [DataMember] 
    public ComponentIdentifier Id { get; set; } 
} 

[DataContract] 
public struct ComponentIdentifier 
{ 
    [DataMember] 
    public long identifier; 
} 

class ComponentIdentifierSurrogate : IDataContractSurrogate 
{ 
    public Type GetDataContractType(Type type) 
    { 
     if (type == typeof(ComponentIdentifier)) 
      return typeof(string); 
     return type; 
    } 

    public object GetObjectToSerialize(object obj, Type targetType) 
    { 
     if (obj is ComponentIdentifier) 
      return ((ComponentIdentifier)obj).identifier.ToString(); 
     return obj; 
    } 

    ... 
} 

public static string Serialize(object obj, IDataContractSurrogate surrogate) 
{ 
    using (MemoryStream memoryStream = new MemoryStream()) 
    using (StreamReader reader = new StreamReader(memoryStream)) 
    { 
     DataContractSerializer serializer = new DataContractSerializer(obj.GetType(), null, int.MaxValue, false, false, new ComponentIdentifierSurrogate()); 
     serializer.WriteObject(memoryStream, obj); 
     memoryStream.Position = 0; 
     return reader.ReadToEnd(); 
    } 
} 

Вариант 3:

static void Main(string[] args) 
{ 
    var serializeMe = new Foo() { Id = new ComponentIdentifier() }; 
    var xml = Serialize(serializeMe); 
    Console.WriteLine(xml); 
    Console.ReadKey(); 
} 

[DataContract] 
public class Foo 
{ 
    [DataMember] 
    public ComponentIdentifier Id { get; set; } 
} 

[DataContract, JsonConverter(typeof(ComponentIdentifierJsonConverter))] 
public struct ComponentIdentifier 
{ 
    [DataMember] 
    private long identifier; 

    public class ComponentIdentifierJsonConverter : JsonConverter 
    { 
     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 
      writer.WriteValue(((ComponentIdentifier)value).identifier.ToString()); 
     } 

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
     { 
      return new ComponentIdentifier() { identifier = int.Parse((string)JToken.ReadFrom(reader)) }; 
     } 

     public override bool CanConvert(Type objectType) 
     { 
      if (objectType == typeof(ComponentIdentifier)) 
       return true; 
      return false; 
     } 
    } 
} 

public static string Serialize(object obj) 
{ 
    var json = JsonConvert.SerializeObject(obj); 
    var xml = JsonConvert.DeserializeXNode(json); 
    xml = new XDocument(
     new XDeclaration("1.0", "utf-8", "yes"), 
     new XElement(obj.GetType().Name, xml.Root)); 
    return xml.ToString(); 
} 

Успехов!