2010-06-30 38 views
0

考慮以下class和struct對象序列化的AJAX,WCF和ViewState中

public class Entity { 
    public IdType Id {get;set;} 
    public string Data {get;set;} 
} 

[TypeConverter(IdTypeConverter))] 
public struct IdType { 
    ... any data ... 
} 

的IdTypeConverter可這裏的idtype從結構和字符串轉換。

現在,我想要的是這個類可以爲AJAX,WCF和ViewState序列化。 senario可以是一個WCF Web服務,它將一個Entity []數組提供給一個DataSource。並且綁定到數據源的自定義控件將該類保存到ViewState中,並將數據發送到客戶端代碼。

只需在所有序列化類型中添加一個[Serializable]屬性即可輕鬆實現。但我不希望IdType被序列化,而是要轉換爲字符串。因此,JSON表示應該是

{ 'Id'=>'StringRepresentationOfId', 'Data'=>'foo' } 

這將類似地是WCF和ViewState的最佳序列化。

另一種解決辦法是寫另一個類

public class JsonEntity { 
    public JsonEntity(Entity from) { 
     Id = from.Id; 
     Data = from.Data; 
    } 
    public string Id {get;set;} 
    public string Data {get;set;} 
} 

,並使用這個JsonSerialization。但我不喜歡這樣,因爲這意味着將數據發送給客戶端的控件知道實體類型。

實際的問題是:是否可以使用屬性定製JsonSerialization而不破壞WCF和ViewState序列化?

編輯: 像「不可能」的答案會滿足我,因爲我會停止嘗試。

回答

1

從我讀過的,用於ViewState序列化的LosFormatter類檢查是否存在給定對象的TypeConverter並使用它,因此您應該在其中覆蓋。

This article描述瞭如何創建自己的JavaScriptConverter來執行自定義序列化。您必須實現的Serialize方法返回IDictionary<string, object>,因此您可能必須爲您的Entity類而不是您的IdType結構創建JavaScriptConverter類。下面是一個例子,雖然我沒有機會去測試它:

注意:在我的文章中的例子只是查找相關TypeConverter for IdType爲了將其轉換爲字符串,但除非有一個這樣做的具體原因你可能只是調用一個特定的函數(例如覆蓋ToString),它直接返回字符串表示,而不是像我的示例代碼那樣查找TypeConverter。

public class EntityJsonConverter : System.Web.Script.Serialization.JavaScriptConverter 
{ 
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) 
    { 
     if (obj == null) 
      throw new ArgumentNullException("obj"); 

     Entity entity = obj as Entity; 
     if (entity != null) 
     { 
      var values = new Dictionary<string, object>(); 
      TypeConverter idTypeConverter = TypeDescriptor.GetConverter(entity.Id); 
      if (idTypeConverter != null) 
      { 
       if (idTypeConverter.CanConvertTo(typeof(string))) 
        values.Add("Id", idTypeConverter.ConvertTo(entity.Id, typeof(string))); 
       else 
        throw new SerializationException(string.Format("The TypeConverter for type \"{0}\" cannot convert to string.", this.GetType().FullName)); 
      } 
      else 
       throw new SerializationException(string.Format("Unable to find a TypeConverter for type \"{0}\".", this.GetType().FullName)); 

      values.Add("Data", serializer.Serialize(entity.Data)); 

      return values; 
     } 
     else 
      throw new ArgumentException(string.Format("Expected argument of type \"{0}\", but received \"{1}\".", typeof(Entity).FullName, obj.GetType().FullName), "obj"); 
    } 

    public override IEnumerable<Type> SupportedTypes 
    { 
     get { yield return typeof(Entity); } 
    } 
} 

如果你也想你的XML序列化描述的行爲,你可以有這裏的idtype結構實現IXmlSerializable接口。下面是使用爲IdType結構定義的TypeConverter的WriteXml方法實現的一個示例:

void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer) 
    { 
     TypeConverter converter = TypeDescriptor.GetConverter(this); 
     if (converter != null) 
     { 
      if (converter.CanConvertTo(typeof(string))) 
       writer.WriteString(converter.ConvertTo(this, typeof(string)) as string); 
      else 
       throw new SerializationException(string.Format("The TypeConverter for type \"{0}\" cannot convert to string.", this.GetType().FullName)); 
     } 
     else 
      throw new SerializationException(string.Format("Unable to find a TypeConverter for type \"{0}\".", this.GetType().FullName)); 
    } 
+0

這個JavaScriptConverter類型看起來不錯。有沒有告訴JsonSerializer使用自定義JavaScriptConverter的屬性? – 2010-06-30 20:13:34

+0

我不認爲這是一個屬性,但請查閱http://nayyeri.net/custom-json-serialization-in-asp-net-ajax上的文章。它顯示瞭如何將JavaScriptConverter註冊到配置文件中。不過,我還沒有機會驗證這一點。 – 2010-06-30 20:23:12

1

另一種類似於創建僅用於序列化的代理類的解決方案是使用[NonSerialized()]屬性。

IdType可能是不可序列化的,而另一個可序列化的字符串屬性可以作爲代理實現(這將在get或set-分配給IdType或從IdType讀取)。

該解決方案甚至可以使用面向方面的編程看起來優雅。

+0

當然!到目前爲止,這是解決json部分的唯一解決方案,避免了序列化數據的控制必須在編譯時知道類型。雖然我不喜歡數據實體上額外的公共字段。 – 2010-06-30 20:22:00

相關問題