company_banner

Готовим ASP.NET Core: создаем свой кроссплатформенный модульный фреймворк

    Мы продолжаем нашу колонку по теме ASP.NET Core очередной публикацией от Дмитрия Сикорского ( DmitrySikorsky) — руководителя компании «Юбрейнианс» из Украины. В этот раз Дмитрий рассказывает о своем опыте разработки модульного кроссплатформенного фреймворка на базе ASP.NET Core. Предыдущие статьи из колонки всегда можно прочитать по ссылке #aspnetcolumn — Владимир Юнев
    Из-за специфики моей задачи, последнее время достаточно много приходится размышлять о модульной и расширяемой архитектуре веб-приложений на ASP.NET Core (а до этого — на ASP.NET предыдущей версии). В результате появился ExtCore — небольшой кроссплатформенный фреймворк с открытым кодом, позволяющий буквально простым подключением NuGet-пакета превратить ваше веб-приложение в модульное и расширяемое.


    Основные возможности


    ExtCore умеет обнаруживать и использовать типы (а также, представления и статический контент), определенные как в проектах (в виде исходного кода или NuGet-пакетов), на которые есть явные ссылки в зависимостях, так и в проектах, которые размещены в определенной папке в виде скомпилированных DLL-сборок.

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

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

    aspnetcolumngithubСовет! Вы можете попробовать все самостоятельно или загрузив исходный код из GitHub https://github.com/ExtCore/ExtCore-Sample.

    Как это работает


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

    Далее, все обнаруженные сборки, соответствующие критериям отбора, помещаются в класс-контейнер ExtensionManager, откуда они могут быть получены в любой момент откуда угодно (т. е. как из основного проекта приложения, так и из любого другого проекта). Эти сборки «регистрируются» как источники для поиска контроллеров (все контроллеры из сборок, на которые есть явные ссылки, обнаруживаются ASP.NET автоматически, а вот об остальных нужно сообщить дополнительно, «вручную»), представлений (и в виде ресурсов, и предварительно скомпилированных) и статического контента.

    После этого производится выполнение ряда методов IExtension среди экземпляров доступных реализаций этого интерфейса. Так расширения получают возможность выполнить свой код во время выполнения методов ConfigureServices, Configure и т. д.

    Рекомендуемая структура расширения


    Для упрощения понимания и сохранения единообразия, удобно придерживаться следующей структуры при разработке собственных расширений (где X — название вашего расширения):

    • YourApplication.X;
    • YourApplication.X.Frontend;
    • YourApplication.X.Backend;
    • YourApplication.X.Data.Models;
    • YourApplication.X.Data.Abstractions;
    • YourApplication.X.Data.SpecificStorageA;
    • YourApplication.X.Data.SpecificStorageB;
    • YourApplication.X.Data.SpecificStorageC;
    • и так далее.

    YourApplication.X

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

    YourApplication.X.Frontend и YourApplication.X.Backend

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

    ExtCore поддерживает два варианта для работы с представлениями (одновременно): представления в виде ресурсов и предварительно скомпилированные представления. Если кратко, я рекомендую использовать второй вариант. Более подробно о методах работы с представлениями, примененными в ExtCore, можно почитать в статье Готовим ASP.NET Core: поговорим про нестандартные подходы при работе с представлениями.

    Работа со статическим контентом также не вызывает затруднений. В статье Готовим ASP.NET Core: как представить статический контент в виде ресурсов подробно описан используемый в ExtCore метод. Если резюмировать статью, то необходимый статический контент помещается в сборки в виде ресурсов и затем эти сборки «регистрируются» как поставщики файлов (file providers), что делает возможным использование ресурсов практически как обычных физических файлов (в т. ч. с прямым доступом по HTTP).

    Интересно, что областью видимости как представлений, так и статического контента является все приложение. Это означает, что одни расширения могут использовать содержимое других расширений и наоборот. Более того, расширения могут использовать представления и статический контент из основного веб-приложения. Таким образом можно, например, описать логику в проектах расширения, но дать возможность пользователю определить то, как все будет выглядеть, прямо в основном приложении.

    YourApplication.X.Data.*

    Проекты, описывающие работу с данными. Более подробно об этом ниже.

    Работа с данными

    ExtCore дополнительно имеет опциональное расширение ExtCore.Data, реализующее весь необходимый базовый функционал для работы с данными. Центральным элементом расширения является интерфейс IStorage (единица работы). Этот интерфейс описывает всего 2 метода: GetRepository и Save. Реализация GetRepository обнаруживает и возвращает доступный экземпляр репозитория, реализующего запрошенный интерфейс (а также, IRepository) и следит за тем, чтобы все репозитории имели единый контекст хранилища (интерфейс IStorageContext).

    Если требуется какая-то регистрация типов сущностей из различных расширений (как, например, в случае с EntityFramework), это может быть легко достигнуто при помощи чего-то вроде интерфейса IModelRegistrar, который применяется в ExtCore.Data.EntityFramework.Sqlite и ExtCore.Data.EntityFramework.SqlServer. Тестовый проект (ссылка на него в конце статьи) иллюстрирует этот подход.

    Структура расширения следующая:

    • ExtCore.Data;
    • ExtCore.Data.Models.Abstractions;
    • ExtCore.Data.Abstractions;
    • ExtCore.Data.EntityFramework.Sqlite;
    • ExtCore.Data.EntityFramework.SqlServer.

    ExtCore.Data

    Проект содержит класс, реализующий интерфейс IExtension. Этот класс при запуске приложения выполняет код, который обнаруживает доступную реализацию интерфейса IStorage (см. ниже) и регистрирует ее во встроенном в ASP.NET Core DI, чтобы любой контроллер затем смог получить ее экземпляр при необходимости. Удобно, что можно изменять тип поддерживаемого хранилища путем простого изменения ссылки в зависимостях или копирования DLL-файла.

    ExtCore.Data.Models.Abstractions

    Проект описывает интерфейс IEntity, который должны реализовать все сущности во всех расширениях.

    ExtCore.Data.Abstractions

    Проект описывает ключевые интерфейсы IStorageContext, IStorage и IRepository, о которых я рассказал выше. В собственных расширениях в проекты с именами вроде YourApplication.X.Data.Abstractions я помещаю интерфейсы репозиториев, чтобы затем работать через них без привязки к реализации конкретного хранилища.

    ExtCore.Data.EntityFramework.Sqlite и ExtCore.Data.EntityFramework.SqlServer

    Проект содержит классы, реализующие интерфейсы из ExtCore.Data.Abstractions для конкретных хранилищ (в данном случае это Sqlite и SqlServer).

    Выводы


    В настоящий момент — это лишь альфа-версия. У меня есть много планов по развитию проекта (подключение и отключение расширений в любой момент и общая оптимизация; также хочу поработать над классом ExtensionManager, добавить удобную возможность получения доступных реализаций заданных интерфейсов, а не только IExtension). Я использую этот фреймворк в своем проекте (CMS). Насколько могу судить — получилось удобно и гибко. Буду рад услышать замечания и критику. Спасибо!

    Вот ссылка на исходники: https://github.com/ExtCore/ExtCore.

    А вот ссылка на готовый тестовый проект: https://github.com/ExtCore/ExtCore-Sample.

    Авторам


    Друзья, если вам интересно поддержать колонку своим собственным материалом, то прошу написать мне на vyunev@microsoft.com для того чтобы обсудить все детали. Мы разыскиваем авторов, которые могут интересно рассказать про ASP.NET и другие темы.

    Об авторе


    Сикорский Дмитрий Александрович
    Компания «Юбрейнианс» (http://ubrainians.com/)
    Владелец, руководитель
    DmitrySikorsky

    Анонс! Глубокий интенсив на конференции DevCon 2016


    image

    Мы рады объявить о проведении глубокого интенсив-курса по ASP.NET Core в рамках [конференции DevCon 2016](https://events.techdays.ru/DevCon/2016/registration). Этот курс будет проходить во второй день конференции и займет полный день конференции в течение 6 часов.

    Разработка современных веб-приложений на открытой платформе ASP.NET 5
    В рамках этого интенсива участники примут участие в увлекательном и полном приключений путешествии, посвященном разработке веб-приложений на новейшей платформе ASP.NET 5. Мы пройдем весь путь от нуля до полноценного приложения, развернутого в облаке. И по дороге участники смогут остановиться для изучения внутреннего устройства ASP.NET, работы с реляционными и NoSQL базами данных с помощью Entity Framework 7, разработки приложений на фреймворке MVC, построении моделей, представлений и бизнес-логики, создании REST API, организации процессов непрерывной разработки и тестирования с помощью Git и Visual Studio Online, а также развертывания с помощью Azure и контейнеров Docker. В конце путешествия все участники пройдут посвящение и станут заслуженными рыцарями ASP.NET.

    Регистрация на конференцию DevCon 2016 уже открыта! Регистрируйтесь здесь.
    Microsoft
    490.83
    Microsoft — мировой лидер в области ПО и ИТ-услуг
    Share post

    Similar posts

    Comments 0

    Only users with full accounts can post comments. Log in, please.