Как десериализация WCF создает экземпляры объектов без вызова конструктора?

С десериализацией WCF творится некое волшебство. Как он создает экземпляр типа контракта данных без вызова его конструктора?

Например, рассмотрим этот контракт данных:

[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
}

При получении экземпляра этого объекта через DataContractSerializer вы увидите, что поле _wasConstructorCalled - это false.

Итак, как это делает WCF? Может ли этот прием использовать и другие, или он скрыт от нас?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
79
0
19 512
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

FormatterServices.GetUninitializedObject() создаст экземпляр без вызова конструктора. Я нашел этот класс, используя Отражатель и покопавшись в некоторых основных классах сериализации .Net.

Я протестировал его, используя приведенный ниже пример кода, и похоже, что он отлично работает:

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

Ну, я ранее публиковал неправильный ответ (теперь удален), поэтому я чувствовал себя виноватым. Нет ничего лучше, чем ушибить эго программиста, чтобы заставить его провести какое-то исследование.

Jason Jackson 09.10.2008 20:54

Кто-нибудь еще сейчас задается вопросом, как же тогда работает FormatterServices.GetUninitializedObject? Отражение?

harpo 27.06.2010 07:57

Если я помню, это вызов в собственный код. Я не мог проследить это дальше по кроличьей норе с помощью Reflector.

Jason Jackson 28.06.2010 07:39

Странно - я запустил этот код в linqpad и получил: 0 0 на выходе. На самом деле это имеет смысл для меня, поскольку инициализаторы полей встроены в ctors AFAIK

bushed 06.09.2011 20:11

@bushed правильный. Выложил скриншот с кодом и результатом здесь. Сначала я подумал, что это может быть разница в версиях .NET framework (так как ответу уже 4 года), но я проверил 2.0 и 4.0, и они оба пишут 0 и 0 в консоль. Джейсон Джексон, не могли бы вы обновить свой пост, чтобы отразить эти выводы?

Oliver 15.11.2012 13:11

Да, FormatterServices.GetUninitializedObject () - это источник волшебства.

Если вы хотите выполнить какую-либо специальную инициализацию, см. Это. http://blogs.msdn.com/drnick/archive/2007/11/19/serialization-and-types.aspx

+1 для справки, [OnDeserialized] был для меня решением!

bas 04.11.2014 21:28

Другие вопросы по теме