Tôi có đoạn mã sau:DataContract serialization ngoại lệ (tên hợp đồng dữ liệu không mong đợi)
[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();
}
}
Khi tôi chạy, tôi nhận được ngoại lệ này:
Loại 'Json_Dictionary_Test.TestContract' với dữ liệu tên hợp đồng 'TestContract: http://schemas.datacontract.org/2004/07/Json_Dictionary_Test' không được mong đợi. Thêm bất kỳ loại nào không được biết đến tĩnh vào danh sách các kiểu đã biết - ví dụ, bằng cách sử dụng thuộc tính KnownTypeAttribute hoặc bằng cách thêm chúng vào danh sách các kiểu đã biết được truyền cho DataContractSerializer.
Nhưng tôi không hiểu điều đó! Như tôi biết, KnownTypeAttribute được sử dụng chỉ trong deserialization, và nếu có thừa kế, phải không? Nhưng đây chỉ là serialization. Và không có thành viên datacontract hoạt động tốt.
Bất kỳ ý tưởng nào?
Tôi đã tìm ra điều gì đó hiệu quả! Có một lớp cha với một danh sách KnownTypes, mà tôi điền vào với mọi tầng lớp trẻ và điều đó sẽ được sử dụng trong serialization:
[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* {
...
}
...
Giải pháp tốt! Điều này sẽ giúp tôi tiết kiệm rất nhiều thời gian. Thay vì làm cho tất cả các lớp serializable một lớp con tôi chỉ kiểm tra xem chúng có thuộc tính DataContract hoạt động tốt hơn cho tôi không: if (! Type.IsAbstract && type.IsDefined (typeof (DataContractAttribute), true)) { knownTypes. Thêm (loại); } – rob