// Динамическое создание типа.
public class Program {
static void Main(string[] args) {
// Попытка загрузить локальную копию CarLibrary.
Assembly a = null;
try {
a = Assembly.Load("CarLibrary");
} catch(FileNotFoundException e) {
Console.WriteLine(e.Message);
Console.ReadLine;
return;
}
// Получение метаданных типа Minivan.
Type miniVan = a.GetType("CarLibrary.MiniVan");
// Динамическое создание Minivan.
object obj = Activator.Createlnstance(miniVan);
}
}
Обратите внимание на то, что метод Activator.CreateInstance возвращает обобщенный System.Object, а не строго типизированный MiniVan. Поэтому если к переменной obj вы примените операцию, обозначаемую точкой, то не увидите никаких членов типа MiniVan. На первый взгляд, можно предположить, что эта проблема решается с помощью явного преобразования типа, но ведь программа не имеет никаких указаний на то, что MiniVan должен иметь при выборе какие-либо преимущества.
Весь смысл динамической привязки заключается в создании экземпляров объектов, для которых нет статической информации. Но как при этом можно вызвать методы объекта MiniVan, сохраненного в переменной System.Object? Ответ: с помощью отображений.
Вызов методов без параметров
Предположим, что нам нужно вызвать метод TurboBoost типа MiniVan. Вы помните, что этот метод приводит двигатель в "абсолютно нерабочее" состояние и генерирует появление информационного блока сообщения. Первым нашим шагом должно быть получение типа MethodInfо для метода TurboBoost с помощью Type.GetMethod. Получив MethodInfo, мы сможем вызвать Minivan.TurboBoost с помощью Invoke. Для MethodInfo.Invoke необходимо указать все параметры, которые должны быть переданы методу, представленному с помощью MethodInfo. Эти параметры представляются массивом System.Object (поскольку метод может иметь любое число параметров любого типа).
Наш метод TurboBoost не имеет параметров, поэтому для него указывается null (в данном случае это и означает отсутствие параметров у метода). Модифицируйте метод Main так.
static void Main(string[] args) {
// Попытка загрузить локальную копию CarLibrary.
...
// Получение типа MiniVan.
Type miтiVan = a.GetType("CarLibrary.MiniVan");
// Динамическое создание MiniVan.
object obj = Activator.CreateInstance(miniVan);
// Получение информации о TurboBoost.
MethodInfo mi = miniVan.GetMethod("TurboBoost");
// Вызов метода ('null' означает отсутствие параметров) .
mi.Invoke(obj, null);
}
После этого вы сможете лицезреть сообщение, подобное показанному на рис. 12.5.
Рис. 12.5. Вызов метода в условиях динамической привязки
Вызов методов с параметрами
Чтобы показать пример динамического вызова метода, имеющего параметры, предположим, что тип MiniVan определяет метод, который называется TellChildToBeQuiet.
// Усмирение вопящих…
public void TellChildToBeQuiet(string kidName, int shameIntensity) {
for (int i = 0; i ‹ shameIntensity; i++)
MessageBox.Show("Потише, {0}!!", kidName);
}
Метод TellChildToBeQuiet (приказать ребенку успокоиться) имеет два параметра: строковое представление имени ребенка и целое число, отражающее степень вашего раздражения. При использовании динамического связывания параметры упаковываются в массив объектов System.Object. Для вызова этого нового метода добавьте в свой метод Main следующий программный код.
// Динамический вызов метода с параметрами.
object[] paramArray = new object[2];
paramArray[0] = "Фред"; // Имя ребенка.
paramArray[1] = 4; // Степень досады.
mi = miniVan.GetMethod("TellChildToBeQuiet");
mi.Invoke(obj, paramArray);