#c_sharp #aspnet #aspnet_mvc #архитектура
Мне необходимо реализовать несколько сайтов на ASP.NET MVC (C#). Во всех сайтах есть общие компоненты (пользователи (регистрация, вход, личные сообщения, восстановление пароля и т.д.), группы, админка, новости и т.д.). Соответственно, я хочу сделать одну общую библиотеку для использования во всех проектах. Проблема заключается в том, что нужно иметь возможность добавлять поля классам библиотеки, при этом и библиотека должна знать о новых полях (для правильной загрузки из бд (используется OrmLite) и кэширования (используется redis)). К тому же хотелось бы избежать конверсий типов или указания generic аргументов в коде сайта: var user = (MyUser)User.Load(id); var user = User.Load(id); Например, базово класс User имеет поля id и name. На сайте 1 нужно добавить поле email. А на сайте 2 нужно добавить поле phone (вместо email). Если бы была одна библиотека (assembly), то это легко решалось бы с помощью partial class. Есть у кого идеи, как решить данную задачу?
Ответы
Ответ 1
Вы смотрите на partial классы под неверным углом зрения. Думаю лучшее объяснение того в чем здесь неточность - это описание причин, по которым частичные классы были созданы. В первой версии C# частичных классов не было и это приводило к сложностям в работе с генерируемым кодом. Например, если вы сейчас используете Windows Forms, то код формы, который генерируется дизайнером, располагается в одном файле, а код, который пишете для формы вы - в другом. В C# 1 все лежало в одном файле и это вызывало серьезные проблемы. С одной стороны вы должны были вести себя осторожно, чтобы не сломать сгенерированный код, с другой стороны генератор кода должен был обходить стороной ваш код. И эти проблемы возможны не только в gui-фреймворках, генерирующих код для создания графического интерфейса. Генерация кода используется, например, в ORM. Наконец, вы сами можете захотеть написать свой генератор. Появление частичных классов в C# 2 решило эту проблему. Именно для этого были созданы частичные классы - чтобы была возможность описать один класс в нескольких файлах. Это позволило изолировать генерируемый код в отдельных файлах. С тех пор были придуманы другие способы использования частичных классов, но и в этих способах причина применения частичных классов та же - необходимость разделить один класс на несколько файлов. Например: при написании unit-тестов обычно на каждый тестируемый класс создается один класс с тестами. Класс с тестами часто становится очень большим, намного большим чем тестируемый класс. В таких случаях класс с тестами можно сделать частичным и разделить на несколько файлов при рефакторинге кода часто встречается задача декомпозиции большого класса. Частичные классы в этом случае могут упростить работу. Можно сначала сделать класс частичным и безопасно разделить его на несколько файлов. И только когда все швы окончательно проясняться, выполнить реальное разделение на несколько классов. Эти способы применения частичных классов отличаются от основного, но в них частичные классы служат той же цели: они позволяют описать один класс в нескольких файлах. То что собираетесь сделать вы - совсем другое дело. Вы собираетесь описать несколько классов с помощью синтаксиса частичных классов. То есть вы хотите описать несколько классов так, как будто это один класс. Более того, вы пытаетесь найти способ описать этот класс так, чтобы он лежал в нескольких сборках. Это равносильно кирпичу, который делят между собой стены соседних зданий. Поэтому ответ на ваш вопрос такой - аналога partial class для разных assemblies не существует, вряд ли когда то будет существовать и не стоит пытаться его сымитировать.Ответ 2
partial-классы между сборками существовать не могут. Зато можно сделать так, чтобы два проекта собирались в итоге в одну и ту же сборку. Делается это так. Открываем проект с библиотекой, и дописываем ближе к концу что-то наподобие вот этого:Теперь открываем файл с основным проектом, и дописываем вот такое: Все, теперь при компиляции все файлы с исходным кодом из библиотеки окажутся как бы включенными в ваш основной проект. Разумеется, это еще не все - ведь проект состоит не только из файлов с исходным кодом. Как минимум, придется таким же образом импортировать зависимости из библиотеки (References) - а также переписать логику загрузки пакетов из репозитория NuGet. Если в библиотеке есть ресурсы (EmbeddedResource) - понадобится импортировать еще и их. Но это все - решаемые проблемы. Также может возникнуть проблема с R# - он не понимает динамического добавления файлов в проект. Для него понадобится включить проект с библиотекой как обычную зависимость - а потом не забыть убрать средствами MSBuild перед компиляцией: Так что в целом то, что вы хотите, вполне достижимо. Но подумайте - не будет ли наследование с обобщенными типами проще?
Комментариев нет:
Отправить комментарий