Làm thế nào để giải mã WCF khởi tạo các đối tượng mà không cần gọi một hàm tạo?


79

Có một số điều kỳ diệu xảy ra với WCF deserialization. Làm cách nào để nó khởi tạo một thể hiện của kiểu hợp đồng dữ liệu mà không cần gọi hàm tạo của nó?

Ví dụ: hãy xem xét hợp đồng dữ liệu này:

[DataContract]
public sealed class CreateMe
{
   [DataMember] private readonly string _name;
   [DataMember] private readonly int _age;
   private readonly bool _wasConstructorCalled;

   public CreateMe()
   {
      _wasConstructorCalled = true;
   }

   // ... other members here
}

Khi lấy một thể hiện của đối tượng này thông qua DataContractSerializerbạn sẽ thấy rằng trường _wasConstructorCalledfalse.

Vậy WCF thực hiện điều này như thế nào? Đây có phải là một kỹ thuật mà những người khác cũng có thể sử dụng, hay nó bị che giấu khỏi chúng ta?

Câu trả lời:


102

FormatterServices.GetUninitializedObject()sẽ tạo một thể hiện mà không cần gọi một hàm tạo. Tôi đã tìm thấy lớp này bằng cách sử dụng Reflector và tìm hiểu một số lớp nối tiếp .Net cốt lõi.

Tôi đã thử nghiệm nó bằng cách sử dụng mã mẫu bên dưới và có vẻ như nó hoạt động rất tốt:

using System;
using System.Reflection;
using System.Runtime.Serialization;

namespace NoConstructorThingy
{
    class Program
    {
        static void Main()
        {
            // does not call ctor
            var myClass = (MyClass)FormatterServices.GetUninitializedObject(typeof(MyClass));

            Console.WriteLine(myClass.One); // writes "0", constructor not called
            Console.WriteLine(myClass.Two); // writes "0", field initializer not called
        }
    }

    public class MyClass
    {
        public MyClass()
        {
            Console.WriteLine("MyClass ctor called.");
            One = 1;
        }

        public int One { get; private set; }
        public readonly int Two = 2;
    }
}

http://d3j5vwomefv46c.cloudfront.net/photos/large/687556261.png


6
À, trước đây tôi đã đăng một câu trả lời sai (giờ đã bị xóa) nên tôi cảm thấy có lỗi. Không có gì giống như đánh bầm dập cái tôi của một lập trình viên để khiến anh ta thực hiện một số nghiên cứu.
Jason Jackson

3
Có ai khác đang thắc mắc, sau đó FormatterServices.GetUninitializedObject hoạt động như thế nào không? Phản ánh?
harpo

Nếu tôi gọi nó thành mã gốc. Tôi không thể theo dõi điều này xa hơn nữa xuống lỗ thỏ với Reflector.
Jason Jackson

6
Kỳ lạ - Tôi chạy mã đó trong linqpad và tôi nhận được: 0 0 như đầu ra. Trên thực tế, điều đó có ý nghĩa với tôi vì các bộ khởi tạo trường được gắn liền với các ctors AFAIK
bushed vào

1
@bush là chính xác. Tôi đã đăng một ảnh chụp màn hình với mã và kết quả ở đây . Lúc đầu, tôi nghĩ rằng nó có thể là một sự khác biệt trong các phiên bản .NET framework (vì câu trả lời đã được 4 tuổi) nhưng tôi đã kiểm tra 2.0 và 4.0 và cả hai đều ghi 0 và 0 vào bảng điều khiển. Jason Jackson, Bạn có thể cập nhật bài đăng của mình để phản ánh những phát hiện này không?
Oliver

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.