Sau khi đào sâu vào các nguồn Newtonsoft.Json Tôi có thể cho bạn biết thuật toán của việc khởi tạo đối tượng được sử dụng ở đó. Và có, hàm tạo là gần như luôn được gọi (*). Câu hỏi chỉ là "cái nào?" Đây là phiên bản đầy màu sắc của câu trả lời:
TL; DR Trước hết, Newtonsoft.Json tạo JsonContract
của các loại mà bạn đang đi để deserialize. Đó là lớp trừu tượng. Và nó có triển khai khác nhau cho từ điển, mảng, đối tượng, vv Trong trường hợp của bạn JsonObjectContract
sẽ được tạo. Hợp đồng chứa nhiều siêu dữ liệu khác nhau về loại deserialized. thú vị nhất đối với chúng tôi là:
IsInstantiable
- xác định liệu loại deserialized là instantiable (xem dưới đây)
Properties
- đó là tập hợp các thuộc tính đối tượng
DefaultCreator
- Phương pháp tạo mặc định dùng để tạo ra đối tượng Func<object>
DefaultCreatorNonPublic
- xác định xem hàm tạo mặc định có công khai không
OverrideCreator
- trình tạo không mặc định, được sử dụng nếu JsonConstructorAttribute
là applie d phản đối của constructor
ParametrizedCreator
- tác giả trong đó kêu gọi constructor paramterized, nó được sử dụng nếu chúng ta không có không phải người sáng tạo mặc định cũng không ghi đè
CreatorParameters
- bộ sưu tập các thuộc tính được sử dụng cho tác giả ghi đè hoặc tạo parametrized
MemberSerialization
- giá trị này xác định cách thức các thuộc tính và các trường được tuần tự hóa. Theo mặc định, nó được đặt thành OptOut
- tức là tất cả các thành viên công khai đều được đăng. Nếu bạn muốn loại trừ một số, bạn nên sử dụng thuộc tính JsonIgnore
. Nhưng cũng có tùy chọn Fields
, cho biết tất cả các trường công khai và riêng tư sẽ được tuần tự hóa. Có một số để bật tùy chọn này. Nhưng theo mặc định, nó bị vô hiệu hóa.
Một số siêu dữ liệu này có thể được truy xuất bằng cách phản ánh metdata loại. Ví dụ. IsInstantiable
được tính toán bằng cách kiểm tra xem loại deserialized không phải là trừu tượng và không phải là giao diện. Một số siêu dữ liệu được thêm bởi DefaultContractResolver
. Đặc biệt, nó định nghĩa cách thức đối tượng nên được xây dựng. Trong mã giả:
if (contract.IsInstantiable)
{
if (type has default constructor or its a value type)
{
contract.DefaultCreator = get default (parameterless) constructor;
contract.DefaultCreatorNonPublic = check if default constructor public
}
if (we have constructor marked with JsonConstructorAttribute)
{
contract.OverrideCreator = constructor marked with attribute
contract.CreatorParameters = get properties which match constructor parameters
}
else if (contract.MemberSerialization == MemberSerialization.Fields)
{
// only if the upplication if fully trusted
contract.DefaultCreator = FormatterServices.GetUninitializedObject
}
else if (contract.DefaultCreator == null || contract.DefaultCreatorNonPublic)
{
if (we have one public constructor with parameters)
{
contract.ParametrizedCreator = constructor with parameters;
contract.CreatorParameters = get properties which match ctor parameters
}
}
}
Vì vậy, bạn có thể thấy prioirty đến hàm tạo được đánh dấu bằng thuộc tính JsonConstructorAttribute
. Bạn cũng sẽ gặp lỗi nếu có nhiều hơn một hàm tạo như vậy.
(*) Tiếp theo là trường hợp duy nhất khi đối tượng có thể được tạo mà không cần gọi hàm tạo. Ví dụ. nếu bạn sẽ đánh dấu lớp học với thuộc tính [JsonObject(MemberSerialization = MemberSerialization.Fields)]
để tuần tự hóa các trường riêng tư.
Sau đó, chúng tôi kiểm tra xem chúng tôi có hàm tạo tham số mặc định không phải là riêng tư hay không. Nếu vậy, thì chúng ta đi tìm một hàm tạo khác - một hàm có tham số và phải được công khai. Nếu có nhiều hơn một hàm tạo như vậy, bạn cũng sẽ gặp lỗi.
Và điều cuối cùng cần lưu ý - CraeatorParameters
. Newtonsoft.Json sử dụng sự phản chiếu để lấy các tham số của hàm tạo và sau đó cố gắng tìm đối sánh gần nhất theo tên của các tham số hàm dựng này cho các thuộc tính của đối tượng. Nó cũng kiểm tra loại thuộc tính và thông số để khớp. Nếu không tìm thấy kết quả phù hợp, thì giá trị mặc định sẽ được chuyển tới hàm tạo tham số này.
Nguồn
2017-01-26 10:56:46
bạn có thể kiểm tra trong 1 phút. Đặt breakpoint trong constructor –
Không hoàn toàn, điều này phụ thuộc vào loại serialization/deserialization thực tế. XmlSerialization ví dụ * * sử dụng hàm tạo mặc định. Tuy nhiên điều này là vô nghĩa đối với câu hỏi thực tế ở đây. – HimBromBeere
Bạn biết rằng đó là mã nguồn mở và bạn có thể kiểm tra nó trên github phải không? –