Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

Assembly asm = Assembly.LoadFrom("AttributedCarLibrary");

// Получить информацию о типе VehicleDescriptionAttribute.

Type vehicleDesc =

asm.GetType("AttributedCarLibrary.VehicleDescriptionAttribute");

// Получить информацию о типе свойства Description.

PropertyInfo propDesc = vehicleDesc.GetProperty("Description");

// Получить все типы в сборке.

Type[] types = asm.GetTypes;

//
Пройти по всем типам и получить любые атрибуты VehicleDescriptionAttribute.

foreach (Type t in types)

{

object[] objs = t.GetCustomAttributes(vehicleDesc, false);

// Пройти по каждому VehicleDescriptionAttribute и вывести

// описание, используя позднее связывание.

foreach (object o in objs)

{

Console.WriteLine("-> {0}: {1}\n", t.Name,

propDesc.GetValue(o, null));

}

}

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

}

}

Если вы прорабатывали примеры, рассмотренные ранее в главе, тогда приведенный код должен быть более или менее понятен. Единственный интересный момент здесь связан с применением метода

PropertyInfo.GetValue
, который служит для активизации средства доступа к свойству. Вот как выглядит вывод, полученный в результате выполнения текущего примера:

***** Value of VehicleDescriptionAttribute *****

– > Motorcycle: My rocking Harley

– > HorseAndBuggy: The old gray mare, she ain't what she used to be...

– > Winnebago: A very long, slow, but feature-rich auto

Практическое использование рефлексии позднего связывания и специальных атрибутов

Хотя вы видели многочисленные примеры применения этих приемов, вас по-прежнему может интересовать, когда использовать рефлексию, динамическое связывание и специальные атрибуты в своих программах. Действительно, данные темы могут показаться в большей степени относящимися к академической стороне программирования (что в зависимости от вашей точки зрения может быть как отрицательным, так и положительным аспектом). Для содействия в отображении указанных тем на реальные ситуации необходим более серьезный пример. Предположим, что вы работаете в составе команды программистов, которая занимается построением приложения, соблюдая требование о том, что продукт должен быть расширяемым за счет использования добавочных сторонних инструментов.

Что понимается под расширяемостью? Возьмем IDE -среду Visual Studio. Когда это приложение разрабатывалось, в его кодовую базу были вставлены многочисленные "привязки", чтобы позволить другим производителям программного обеспечения подключать специальные модули к IDE - среде. Очевидно, что у разработчиков Visual Studio отсутствовал какой-либо способ установки ссылок на внешние сборки .NET Core, которые на тот момент еще не были созданы (и потому раннее связывание недоступно), тогда как они обеспечили

наличие в приложении необходимых привязок? Ниже представлен один из возможных способов решения задачи.

1. Во-первых, расширяемое приложение должно предоставлять некоторый механизм ввода, позволяющий пользователю указать модуль для подключения (наподобие диалогового окна или флага командной строки). Это требует динамической загрузки.

2. Во-вторых, расширяемое приложение должно иметь возможность выяснять, поддерживает ли модуль корректную функциональность (такую как набор обязательных интерфейсов), необходимую для его подключения к среде. Это требует рефлексии.

3. В-третьих, расширяемое приложение должно получать ссылку на требуемую инфраструктуру (вроде набора интерфейсных типов) и вызывать члены для запуска лежащей в основе функциональности. Это может требовать позднего связывания.

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

Построение расширяемого приложения

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

CommonSnappableTypes.dll
. Эта сборка содержит определения типов, которые будут использоваться каждым объектом оснастки. На нее будет напрямую ссылаться расширяемое приложение.

CSharpSnapIn.dll
. Оснастка, написанная на С#, в которой задействованы типы из сборки
CommonSnappableTypes.dll
.

VBSnapIn.dll
. Оснастка, написанная на Visual Basic, в которой применяются типы из сборки
CommonSnappableTypes.dll
.

MyExtendableApp.ехе
. Консольное приложение, которое может быть расширено функциональностью каждой оснастки.

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

На заметку! Вы можете подумать о том, что вам вряд ли будет ставиться задача построения консольного приложения, и тут вы вероятно правы! Бизнес-приложения, создаваемые на языке С#, обычно относятся к категории интеллектуальных клиентов (Windows Forms или WPF), веб-приложений/служб REST (ASP.NET Core) или автоматических процессов (функций Azure, служб Windows и т.д.). Консольные приложения применяются здесь, чтобы сосредоточиться на специфических концепциях примеров, в данном случае — на динамической загрузке, рефлексии и позднем связывании. Позже в книге вы узнаете, как строить "реальные" пользовательские приложения с использованием WPF и ASP.NET Core.

Построение мультипроектного решения ExtendableApp

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

Создание решения и проектов с помощью интерфейса командной строки

Поделиться с друзьями: