Динамическое создание конструируемых типов

Учитывая динамическую природу CLR и тот факт, что на самом деле классы и код генерируются во время выполнения, вполне естественно предположить возможность конструирования закрытых типов из обобщений во время выполнения. До настоящего момента все примеры имели дело с созданием типов во время компиляции.

Эта функциональность проистекает из естественного расширения спецификации метаданных для обслуживания обобщений. Тип System.Туре — краеугольный камень функциональности, когда нужно работать с типами динамически внутри CLR, и естественно, он был расширен для того, чтобы иметь дело также и с обобщениями.

Некоторые ориентированные на обобщения методы System.Туре самоочевидны благодаря их именам; к ним относятся GetGenericArguments, GetGenericParameterConstraints и GetGenericTypeDefinition. Эти методы полезны, когда уже есть экземпляр System.Туре, представляющий закрытый тип.

Однако то, что делает все намного интереснее — это метод MakeGenericType, который позволяет передать массив объектов System.Туре, представляющих типы, которые должны быть использованы в списке аргументов для создания результирующего конструируемого типа.

Тех из вас, кто имеет опыт работы с шаблонами С++, обобщения могут время от времени разочаровывать, поскольку им недостает статических возможностей шаблонов. Однако динамические возможности обобщений в конечном итоге перевешивают. Например, создание механизма анализа некоторого языка, основанного на XML, в котором определяются новые типы на основе обобщений, становится очень простым.

Ниже приведен пример использования метода MakeGenericType:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System;
using System.Collections.Generic;
public class EntryPoint
{
static void Main()  {
IList<int> intList =
(IList<int>) CreateClosedType<int> ( typeof(Listo) ); 
IList<double> doubleList = (IList<double>)
CreateClosedType<double> ( typeof (Listo)  );
Console.WriteLine ( intList ); 
Console.WriteLine ( doubleList );
}
static object CreateClosedType<T> ( Type genericType )  { 
Type[] typeArguments = { typeof( T )
};
Type closedType =
genericType.MakeGenericType ( typeArguments ); 
return Activator.Createlnstance ( closedType );
}

Основная часть этого кода содержится внутри обобщенного метода CreateClosed Туре<Т>. В общих чертах вся работа выполняется через ссылки на Туре, созданные из доступных метаданных. Сначала должна быть получена ссылка на обобщенный, открытый тип List, который передан в виде параметра.

После этого просто создается массив экземпляров Туре для передачи методу MakeGenericType, чтобы получить от него ссылку на закрытый тип. Как только эта стадия завершена, единственное, что остается — это вызов Createlnstance на классе System.Activator.

Класс System.Activator — это средство, которое должно использоваться для создания экземпляров типов, известных только во время выполнения. В данном случае вызывается конструктор по умолчанию для закрытого типа. Однако Activator имеет перегрузки Createlnstance, которые позволяют вызывать конструкторы, принимающие параметры.

Чтобы получить экземпляр Туре для типов, вместо метода Туре.GetType применяется операция typeof. Если тип известен во время компиляции, то операция typeof сразу осуществляет поиск по метаданным вместо того, чтобы делать это во время выполнения, что более эффективно.

После запуска предыдущего примера закрытые типы выводятся на консоль с указанием их полностью квалифицированных имен типов, тем самым доказывая правильность создания закрытых типов.

Возможность создания закрытых типов во время выполнения — еще один мощный инструмент, предназначенный для создания высокодинамичных систем. Можно не только объявлять обобщенные типы в коде, чтобы получать гибкий код, но также создавать закрытые типы из этих обобщенных определений во время выполнения. Задумайтесь на минуту о круге задач, которые можно решить с помощью такой техники, и вы поймете, что обобщения — исключительно мощное дополнение к С# и CLR.

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100