LƯU Ý: Tôi đã đi vào rất nhiều chi tiết về JavaScriptSerializer ở đầu câu trả lời của tôi, nếu bạn chỉ muốn đọc về độ phân giải cho vấn đề loại đã biết được đề cập trong câu hỏi gốc, nhảy đến cuối của câu trả lời.
Performance
Dựa trên benchmarks Tôi chạy, các JavaScriptSerializer là xa chậm hơn so với các lựa chọn thay thế khác và có thể mất 2x miễn serialize/deserialize một đối tượng so với DataContractSerializer.
Không cần Known Loại
Điều đó nói rằng, các JavascriptSerializer là linh hoạt hơn ở chỗ nó không yêu cầu bạn phải xác định 'loại nổi tiếng' trước thời hạn, và JSON serialized là sạch hơn ít nhất là trong trường hợp từ điển (xem ví dụ here).
Mặt trái của tính linh hoạt đó xung quanh các loại đã biết là sẽ không thể deserialize cùng chuỗi JSON đó trở về kiểu gốc.Ví dụ, giả sử tôi có một Person
lớp đơn giản:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Và nếu tôi có thể tạo một thể hiện của Dictinoary<string, object>
và thêm một thể hiện của lớp Person
với nó trước khi serializing nó:
var dictionary = new Dictionary<string, object>();
dictionary.Add("me", new Person { Name = "Yan", Age = 30 });
var serializer = new new JavaScriptSerializer();
var json = serializer .Serialize(dictionary);
tôi sẽ nhận JSON sau đây {"me":{"Name":"Yan","Age":30}}
rất sạch sẽ nhưng không có bất kỳ thông tin loại nào. Vì vậy, phải nếu bạn có hai lớp với các định nghĩa thành viên cùng hoặc nếu Person
được subclassed mà không giới thiệu bất kỳ bổ sung thành viên:
public class Employee : Person
{
}
sau đó chỉ đơn giản là không có cách nào cho serializer để có thể đảm bảo rằng các JSON {"Name":"Yan","Age":30}
có thể được deserialized đúng loại.
Nếu bạn deserialize {"me":{"Name":"Yan","Age":30}}
sử dụng JavaScriptSerializer, trong từ điển bạn nhận lại giá trị được liên kết với "tôi" không phải là phiên bản Person
mà thay vào đó là Dictionary<string, object>
.
Nếu bạn muốn nhận được một trường hợp Person
trở lại, bạn có thể (mặc dù bạn có lẽ hầu hết sẽ không bao giờ muốn!) Chuyển đổi mà Dictionary<string, object>
sử dụng phương pháp ConvertToType
helper:
var clone = serializer.Deserialize<Dictionary<string, object>>(json);
var personClone = serializer.ConverToType<Person>(clone["me"]);
Mặt khác, nếu bạn không cần phải lo lắng về việc deserializing những JSON vào đúng loại và JSON serailization không phải là một nút cổ chai hiệu suất (hồ sơ mã của bạn và tìm ra bao nhiêu thời gian CPU dành cho serialization nếu bạn đã không làm như vậy) sau đó tôi muốn nói chỉ cần sử dụng JavaScriptSerializer.
Tiêm Known Loại
NẾU, vào cuối ngày, bạn vẫn cần phải sử dụng DataContractSerializer và cần phải tiêm những KnownTypes, đây là hai điều bạn có thể thử.
1) Chuyển mảng các loại đã biết đến DataContractSerializer constructor.
2) Vượt qua một lớp con của DataContractResolver (với các phương tiện để xác định vị trí các loại quan tâm đến bạn) đến DataContractSerializer constructor
Bạn có thể tạo một 'kiểu registry biết' của các loại mà theo dõi những loại mà có thể được thêm vào từ điển, và nếu bạn kiểm soát tất cả các loại mà bạn sẽ cần phải tiêm vào DataContractSerializer, bạn có thể thử điều đơn giản nhất:
Tạo một lớp KnownTypeRegister
với các phương pháp tĩnh để thêm một loại vào danh sách các loại đã biết:
public static class KnownTypeRegister
{
private static readonly ConcurrentBag _knownTypes = new ConcurrentBag();
public static void Add(Type type)
{
_knownTypes.Add(type);
}
public static IEnumerable Get()
{
return _knownTypes.ToArray();
}
}
Thêm một constructor tĩnh dùng để đăng ký các loại với thanh ghi:
[DataContract]
public class Person
{
static Person()
{
KnownTypeRegister.Add(typeof(Person));
}
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
}
Lấy mảng của các loại được biết đến từ sổ đăng ký khi bạn xây dựng các serializer:
var serializer = new DataContractSerializer(typeof(Dictionary<string, object>), KnownTypeRegister.Get());
Tùy chọn động/tốt hơn là sở hữu e nhưng chúng cũng khó thực hiện hơn, nếu bạn muốn đọc thêm về độ phân giải kiểu động đã biết, hãy xem bài viết MSDN của Juval Lowy về chủ đề here. Ngoài ra, this blog post bởi Carlos Figueira cũng đi vào chi tiết về các kỹ thuật nâng cao hơn như tạo động các loại, cũng đáng đọc trong khi bạn đang ở trên chủ đề!
Tôi rất vui vì những người như thế này. Xin vui lòng không bận tâm để trả lời với các đối số như thế nào WCF đã không được thực hiện cho rằng vv, vv Tôi sẽ đánh giá cao nếu bạn chỉ có thể cho chúng tôi biết nếu có một cách biết hoặc nếu bạn đã ở đó và đã từ bỏ vì lý do hợp lệ (những gì lý do?). – tishma