Язык программирования C#9 и платформа .NET5
3. В-третьих, расширяемое приложение должно получать ссылку на требуемую инфраструктуру (вроде набора интерфейсных типов) и вызывать члены для запуска лежащей в основе функциональности. Это может требовать позднего связывания.
Попросту говоря, если расширяемое приложение изначально запрограммировано для запрашивания специфических интерфейсов, то во время выполнения оно в состоянии выяснять, может ли быть активизирован интересующий тип. После успешного прохождения такой проверки тип может поддерживать дополнительные интерфейсы, которые формируют полиморфную фабрику его функциональности. Именно этот подход был принят командой разработчиков Visual Studio, и вопреки тому, что вы могли подумать, в нем нет ничего сложного!
Построение расширяемого приложения
В последующих разделах будет рассмотрен пример создания расширяемого приложения, которое может быть дополнено функциональностью внешних сборок. Расширяемое приложение образовано из следующих сборок.
•
. Эта сборка содержит определения типов, которые будут использоваться каждым объектом оснастки. На нее будет напрямую ссылаться расширяемое приложение.CommonSnappableTypes.dll•
. Оснастка, написанная на С#, в которой задействованы типы из сборкиCSharpSnapIn.dll.CommonSnappableTypes.dll•
. Оснастка, написанная на Visual Basic, в которой применяются типы из сборкиVBSnapIn.dll.CommonSnappableTypes.dll•
. Консольное приложение, которое может быть расширено функциональностью каждой оснастки.MyExtendableApp.ехеВ приложении будут использоваться динамическая загрузка, рефлексия и позднее связывание для динамического получения функциональности сборок, о которых заранее ничего не известно.
На заметку! Вы можете подумать о том, что вам вряд ли будет ставиться задача построения консольного приложения, и тут вы вероятно правы! Бизнес-приложения, создаваемые на языке С#, обычно относятся к категории интеллектуальных клиентов (Windows Forms или WPF), веб-приложений/служб REST (ASP.NET Core) или автоматических процессов (функций Azure, служб Windows и т.д.). Консольные приложения применяются здесь, чтобы сосредоточиться на специфических концепциях примеров, в данном случае — на динамической загрузке, рефлексии и позднем связывании. Позже в книге вы узнаете, как строить "реальные" пользовательские приложения с использованием WPF и ASP.NET Core.
Построение мультипроектного решения ExtendableApp
Большинство приложений, созданных ранее в книге, были автономными проектами с небольшими исключениями (вроде предыдущего приложения). Так делалось для того, чтобы сохранять примеры простыми и четко ориентированными на демонстрируемые в них аспекты. Однако в реальном процессе разработки обычно приходится работать с множеством проектов в одном решении.
Создание решения и проектов с помощью интерфейса командной строки
Открыв окно интерфейса CLI, введите следующие команды, чтобы создать новое решение, проекты для библиотек классов и консольного приложения, а также ссылки на проекты:
dotnet new sln -n Chapter17_ExtendableAppdotnet new classlib -lang c# -n CommonSnappableTypes-o .\CommonSnappableTypes -f net5.0dotnet sln .\Chapter17_ExtendableApp.sln add .\CommonSnappableTypesdotnet new classlib -lang c# -n CSharpSnapIn -o .\CSharpSnapIn -f net5.0dotnet sln .\Chapter17_ExtendableApp.sln add .\CSharpSnapIndotnet add CSharpSnapin reference CommonSnappableTypesdotnet new classlib -lang vb -n VBSnapIn -o .\VBSnapIn -f net5.0dotnet sln .\Chapter17_ExtendableApp.sln add .\VBSnapIndotnet add VBSnapIn reference CommonSnappableTypesdotnet new console -lang c# -n MyExtendableApp -o .\MyExtendableApp -f net5.0dotnet sln .\Chapter17_ExtendableApp.sln add .\MyExtendableAppdotnet add MyExtendableApp reference CommonSnappableTypesДобавление событий PostBuild в файлы проектов
При компиляции проекта (либо в Visual Studio, либо в командной строке) существуют события, к которым можно привязываться. Например, после каждой успешной компиляции нужно копировать две сборки оснасток в каталог проекта консольного приложения (в случае отладки посредством
) и в выходной каталог консольного приложения (при отладке в Visual Studio). Для этого будут использоваться несколько встроенных макросов.dotnet runВставьте в файлы
иCSharpSnapin.csprojприведенный ниже блок разметки, который копирует скомпилированную сборку в каталог проектаVBSnapIn.vbprojи в выходной каталог(MyExtendableApp):MyExtendableApp\bin\debug\net5.0<Target Name="PostBuild" AfterTargets="PostBuildEvent"><Exec Command="copy $(TargetPath) $(SolutionDir)MyExtendableApp\$(OutDir)$(TargetFileName)/Y 
copy $(TargetPath) $(SolutionDir)MyExtendableApp\$(TargetFileName) /Y" /></Target>Теперь после компиляции каждого проекта его сборка копируется также в целевой каталог приложения
.MyExtendableAppСоздание решения и проектов с помощью Visual Studio
Вспомните, что по умолчанию среда Visual Studio назначает решению такое же имя, как у первого проекта, созданного в этом решении. Тем не менее, вы можете легко изменять имя решения.
Чтобы создать решение
, выберите в меню пункт File►New Project (Файл►Создать проект). В открывшемся диалоговом окне Add New Project (Добавление нового проекта) выберите элемент Class Library (Библиотека классов) и введитеExtendableAppв поле Project name (Имя проекта). Прежде чем щелкать на кнопке Create (Создать), введитеCommonSnappableTypesв поле Solution name (Имя решения), как показано на рис. 17.3.ExtendableAppЧтобы добавить к решению еще один проект, щелкните правой кнопкой мыши на имени решения(
) в окне Solution Explorer и выберите в контекстном меню пункт Add►New Project (Добавить► Новый проект) или выберите в меню пункт File►Add►New Project (Файл►Добавить►Новый проект). При добавлении дополнительного проекта к существующему решению содержимое диалогового окна Add New Project слегка отличается; параметры решения теперь отсутствуют, так что вы увидите только информацию о проекте (имя и местоположение). Назначьте проекту библиотеки классов имяExtendableAppи щелкните на кнопке Create.CSharpSnapIn
