I次のコードを持っています。データをのDataContractシリアル化の例外(データコントラクト名が期待されていない)
タイプ 'Json_Dictionary_Test.TestContract':私は実行すると
[DataContract] class TestContract { private String _Name; private Int32 _Age; [DataMember(Name = "Name")] public String Name { get { return _Name; } set { _Name = value; } } [DataMember(Name = "Age")] public Int32 Age { get { return _Age; } set { _Age = value; } } } [Serializable] public class DNCJsonDictionary<K, V> : ISerializable { Dictionary<K, V> dict = new Dictionary<K, V>(); public DNCJsonDictionary() { } protected DNCJsonDictionary(SerializationInfo info, StreamingContext context) { } public void GetObjectData(SerializationInfo info, StreamingContext context) { foreach(K key in dict.Keys) { info.AddValue(key.ToString(), dict[ key ]); } } public void Add(K key, V value) { dict.Add(key, value); } public V this[ K index ] { set { dict[ index ] = value; } get { return dict[ index ]; } } } public class MainClass { public static String Serialize(Object data) { var serializer = new DataContractJsonSerializer(data.GetType()); var ms = new MemoryStream(); serializer.WriteObject(ms, data); return Encoding.UTF8.GetString(ms.ToArray()); } public static void Main() { DNCJsonDictionary<String, Object> address = new DNCJsonDictionary<String, Object>(); address[ "Street" ] = "30 Rockefeller Plaza"; address[ "City" ] = "New York City"; address[ "State" ] = "NY"; TestContract test = new TestContract(); test.Name = "CsDJ"; test.Age = 28; DNCJsonDictionary<String, Object> result = new DNCJsonDictionary<String, Object>(); result[ "foo" ] = "bar"; result[ "Name" ] = "John Doe"; result[ "Age" ] = 32; result[ "Address" ] = address; // ** --- THIS THROWS AN EXCEPTION!!! --- ** result[ "test" ] = test; Console.WriteLine(Serialize(result)); Console.ReadLine(); } }
が、私はこの例外を取得します契約名 'TestContract:http://schemas.datacontract.org/2004/07/Json_Dictionary_Test'は必要ありません。 KnownTypeAttribute属性を使用するか、DataContractSerializerに渡される既知の型のリストに追加するなど、既知の型のリストに静的に知られていない型を追加します。
しかし、私はそれを理解していません!私が知っているように、KnownTypeAttributeはデシリアライズ時にのみ使用され、継承があればそれはありませんか?しかしここにはシリアライゼーションだけがあります。そして、datacontractメンバーがうまくいなければ。
私は何かを考え出しました!私はすべての子クラスに記入し、それをシリアル化に使用されるKnownTypesリストを持つ親クラスは、あります:
[DataContract]
[KnownType("GetKnownTypes")] // for serialization
class ResultContract {
private static List<Type> KnownTypes { get; set; }
public static List<Type> GetKnownTypes() {
return KnownTypes;
}
static ResultContract() {
KnownTypes = new List<Type>();
try {
foreach(Type type in Assembly.GetExecutingAssembly().GetTypes()) {
if(!type.IsAbstract && type.IsSubclassOf(typeof(ResultContract))) {
KnownTypes.Add(type);
}
}
} catch(Exception ex) {
Console.WriteLine("Fatal error!");
}
}
}
[DataContract]
class TestContract : *ResultContract* {
...
}
...
ニースのソリューション!これは私に多くの時間を節約するだろう。すべてのシリアライズ可能なクラスをサブクラスにする代わりに、DataContract属性が適切かどうかを確認するだけです。if(!type.IsAbstract && type.IsDefined(typeof(DataContractAttribute)、true)) { knownTypes。追加(タイプ); } – rob