Создать экземпляр объекта без вызова конструктора?

В С# существует ли способ создать экземпляр класса без вызова его конструктора?

Предположим, что класс является общедоступным и определяется в сторонней библиотеке, а конструктор является внутренним. Причины, по которым я хочу это сделать, сложны, но было бы полезно узнать, возможно ли использовать какой-то хакерство С#.

ПРИМЕЧАНИЕ. Я специально не хочу вызывать конструктор, поэтому использование отражения для доступа к внутреннему конструктору не является вариантом.

Ответ 1

Я не пробовал это, но есть метод под названием FormatterServices.GetUninitializedObject, который используется во время десериализации.

Заметки из MSDN говорят:

Поскольку новый экземпляр объекта инициализируется до нуля, и нет выполняются конструкторы, объект может не представляет собой состояние, которое считается как действительный для этого объекта.

Ответ 2

На самом деле это звучит так, будто они сделали внутренний конструктор просто так, что вы не можете его создать. Он может иметь метод построения или factory.

Ознакомьтесь с этими статьями:

Предотвращение третьей стороны: Часть 1

Предотвращение выработки третьей стороны: Часть 2

они объясняют рассуждения.

Ответ 3

Вопреки тому, что многие считают, конструктор не имеет ничего общего с созданием объекта вообще (довольно вводящий в заблуждение термин). Конструктор - это специальный метод, который можно вызвать после создания объекта, чтобы этот объект мог правильно инициализироваться. В экземпляре объекта С++ выделяется память для объекта, а в .NET и Java он выделяется и предварительно инициализируется значениями по умолчанию в зависимости от типа полей (0, null, false и т.д.). Затем время выполнения вызывает конструктор. Новый оператор заключает эти два отдельных действия в одну операцию. Deserialization никогда бы не работала в .NET, если было невозможно создать экземпляр без использования конструктора. Тем не менее, так называемый тип ConstructorInfo действует как новый оператор и конструктор при вызове метода Invoke (...).

Ответ 4

Можно было бы получить доступ к конструктору через отражение и вызвать его так (но я не уверен, что он будет работать, поскольку конструктор является внутренним - вам придется его протестировать). В противном случае, из моих знаний, вы не можете создать объект без вызова конструктора.

Ответ 5

См. функцию System.Activator.CreateInstance.

Ответ 6

EDIT: вы обновили свой вопрос, вы хотите построить класс без конструктора. Или вызовите по умолчанию "пустой конструктор".

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

Предполагая, что ваш класс называется Foo:

using System.Reflection;

// If the constructor takes arguments, otherwise pass these as null
Type[] pTypes = new Type[1];
pTypes[0] = typeof(object);    
object[] argList = new object[1];
argList[0] = constructorArgs;

ConstructorInfo c = typeof(Foo).GetConstructor
    (BindingFlags.NonPublic |
     BindingFlags.Instance,
     null,
     pTypes,
     null);

Foo foo = 
    (Foo) c.Invoke(BindingFlags.NonPublic,
                   null, 
                   argList, 
                   Application.CurrentCulture);

Уродливо, но работает.

Конечно, может быть совершенно законная причина помечать конструктор как внутреннюю, поэтому вам следует действительно подумать о логистике того, что вы хотите, прежде чем злоупотреблять этим классом, пройдя по нему с отражением.

Ответ 7

То, что вы просите, - это нарушение философии, на которой было разработано управляемое программирование..Net Framework и С# построены с принципом, что, когда это возможно, объекты должны быть абстрагированы от их основной памяти. Объекты - это объекты, а не структурированный массив байтов. Вот почему вы не можете набрасывать объекты на void-указатели волей-неволей. Когда объекты абстрагируются от их основной памяти, принципиально недействительно предположить, что экземпляр объекта может существовать без вызова конструктора.

Тем не менее, инфраструктура .Net сделала уступки тому факту, что на самом деле объекты фактически представлены в памяти. С некоторым творчеством можно создавать типы значений без вызова их инициализаторов. Однако, если вы чувствуете, что вам нужно это сделать, вы, вероятно, ошибаетесь.

Ответ 8

Вы должны вызвать конструктор для создания объекта. Если нет доступных по своему усмотрению, возможно, вы могли бы использовать библиотеку перезаписи байтов, такую ​​как Mono project Cecil. Он работает как в Windows, так и в Linux. Из некоторых демонстраций, которые я видел, это выглядело довольно круто. Вы можете изменить уровни защиты методов и всевозможные сумасшедшие вещи.

Ответ 9

Если класс (и классы объектов, на которые он ссылается) является Serializable, вы можете создать глубокую копию путем сериализации с использованием BinaryFormatter, который выводит в MemoryStream (создавая байтовый массив байтов []), а затем десериализуем. См. ответы на этот вопрос о преобразовании объекта в байтовый массив. (Но обратите внимание: сохранение байтового массива для использования позже или в другом месте, вероятно, не сработает. IOW не сохраняет массив байтов в файл или другую постоянную форму.)

Ответ 10

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

Кажется, что вы можете создать экземпляр класса без использования его конструкторов, назначив значения его свойствам. Вот адрес, где находится инструкция в MSDN для этого типа экземпляра http://msdn.microsoft.com/en-us/library/bb397680.aspx.

Похоже, что это метод, который не так хорошо известен, потому что я столкнулся с ним в статье в CodeProject, а затем искал его и ничего не нашел об этом, а позже посетил домашнюю страницу MSDN, и было сообщение, связанное со мной к этому точному вопросу. Похоже, что это неизвестный предмет, а не новый, потому что дата в сообщении CodeProject датируется май 2008 года.

Надеюсь, что это поможет кому-то еще в этом google и столкнется с этим вопросом.

Ответ 11

Никто здесь не прояснил, что подразумевается под "Этого не может быть сделано".

Конструктор - это то, что создает объект. Ваш вопрос сродни: "Как я могу построить песчаный замок, не создавая его, как замок?" Вы не можете - все, что у вас будет, это куча песка.

Самое близкое, что вы могли бы сделать, это выделить блок памяти того же размера, что и ваш объект:

byte[] fakeObject = new byte[sizeof(myStruct)];

(ПРИМЕЧАНИЕ: даже это будет работать только в MyStruct - это тип значения)