Определение типа с помощью порождения отражения
Обновлен: Ноябрь 2007
Типы определяются в области действия динамического модуля при помощи метода ModuleBuilder.DefineType. DefineType возвращает TypeBuilder. В этом разделе имя типа всегда представляет собой полный путь, включающий пространство имен. Например, если имя типа Aaa.Bbb.Ccc, считается, что Aaa.Bbb — это пространство имен.
Порождение отражения предоставляет следующие варианты определения типов.
Определение класса или интерфейса с заданным именем.
Определение класса или интерфейса с заданным именем и атрибутами.
Определение класса с заданным именем, атрибутов и базового класса.
Определение класса с заданным именем, атрибутов, базового класса и набора интерфейсов, реализуемых данным классом.
Определение класса с заданным именем, атрибутов, базового класса и размера уплотнения.
Определение класса с заданным именем, атрибутов, базового класса и размера класса в целом.
Определение класса с заданным именем, атрибутов, базового класса, размера уплотнения и размера класса в целом.
Перед использованием типа необходимо вызвать метод TypeBuilder.CreateType. CreateType завершает создание типа. Вслед за вызовом CreateType вызывающий объект может создать экземпляр типа (с помощью метода Activator.CreateInstance) и вызвать элементы типа (с помощью метода Type.InvokeMember). Вызов методов, изменяющих реализацию данного типа, после вызова CreateType, вызовет ошибку. Например, общеязыковая среда выполнения генерирует исключение, если вызывающий объект пытается добавить в тип новые элементы.
Средство инициализации класса создается с помощью метода TypeBuilder.DefineTypeInitializer. DefineTypeInitializer возвращает ConstructorBuilder.
Вложенные типы определяются с помощью одного из методов TypeBuilder.DefineNestedType.
Метод TypeBuilder.AddDeclarativeSecurity добавляет декларативную безопасность в создаваемый тип. AddDeclarativeSecurity можно вызывать несколько раз, задавая при каждом вызове действие по обеспечению безопасности (такие как Demand, Assert, Deny) и устанавливая разрешения, к которым эти действия применяются.
Атрибуты
Интерфейсы описываются с использованием атрибутов TTypeAttributes.Interface и TypeAttributes.Abstract .
Закрытые классы (классы, которые не могут быть расширены) задаются с помощью атрибута TypeAttributes.Sealed.
Несколько атрибутов определяют видимость типа. См. описание перечисления TypeAttributes.
Если задан TypeAttributes.LayoutSequential, загрузчик класса размещает поля в том порядке, в котором они считываются из метаданных. Загрузчик класса учитывает заданный размер записи, но не обрабатывает любые заданные смещения полей. Метаданные сохраняют порядок, в котором происходил выпуск определений полей. Даже при объединении метаданные не будут изменять порядок определений полей. Загрузчик будет принимать заданные смещения полей, только если задан TypeAttributes.ExplicitLayout.
Известные проблемы
Порождение отражения не проверяет, реализовал ли неабстрактный класс, реализующий интерфейс, все методы, объявленные в интерфейсе. Однако если этот класс не реализовал все методы, объявленные в интерфейсе, среда выполнения этот класс не загружает.
Хотя TypeBuilder является производным от Type, некоторые из абстрактных методов, определенных в классе Type, не полностью реализованы в TypeBuilder. Эти методы TypeBuilder создают исключение NotSupportedException. Необходимая функциональность может быть достигнута путем получения созданного типа с помощью методов Type.GetType или Assembly.GetType и отражения полученного типа.