Я испускаю несколько классов, некоторые из которых должны создавать своих сверстников в своих собственных конструкторах. Нет бесконечных рекурсивных зависимостей (поэтому, если A создает B, B не будет создавать A; это верно и для вложенных ссылок [A создает B, создает C означает, что ни B, ни C не будут создавать A]). В настоящее время я работаю над кодом, который генерирует конструкторы, и у меня есть небольшая проблема. Я заранее не знаю порядок зависимостей, поэтому кажется, что у меня есть несколько вариантов:
- Каким-то образом отсортируйте классы по их зависимостям и «создайте» их в порядке их зависимостей, чтобы более зависимые классы имели действительную ссылку на конструктор для захвата.
- Определите все конструкторы отдельно в первом проходе (без фактической генерации IL для методов), чтобы были определены все ссылки на конструктор.
- Каким-то образом кэшируйте определенные конструкторы, чтобы, если конструктор еще не был определен, я мог создать заполнитель ConstructorBuilder, чтобы получить ссылку, которая затем будет получена позже, когда конструктор будет окончательно выпущен.
В настоящее время я пытаюсь использовать вариант (3), и мне было интересно, есть ли уже способ сделать это из TypeBuilder. У меня есть код, который выглядит так (чтобы получить ссылку на конструктор, когда это необходимо):
var fieldType = DefineType(udtField.Type); // This looks up a cached TypeBuilder or creates a placeholder, if needed
var constructor = fieldType.GetConstructor(Type.EmptyTypes);
if (constructor == null)
{
constructor =
fieldType.DefineConstructor(
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
CallingConventions.Standard, Type.EmptyTypes);
}
И мой метод Build в настоящее время начинается так (я не думаю, что это сработает, если конструктор был определен ранее):
private void BuildConstructor()
{
var method =
DefinedType.DefineConstructor(
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
CallingConventions.Standard, Type.EmptyTypes);
var il = method.GetILGenerator();
Есть ли способ найти ConstructorBuilder, который был определен ранее (если он был), без необходимости создавать собственный явный кеш? Кажется, что TypeBuilder должен знать об этом, но я не вижу никакого очевидного способа найти его в документации TypeBuilder.
РЕДАКТИРОВАТЬ:
В итоге я пошел по маршруту (2), который определяет все соответствующие методы во время первого прохода, а затем выдает IL на втором проходе. Мне все еще было бы любопытно, возможно ли получить экземпляры MethodBuilder (или экземпляры ConstructorBuilder) из TypeBuilder для сборщиков, которые уже были определены в другом месте.