Это сценарий.
У меня есть старое приложение на основе плагинов с базой данных, содержащей таблицу articles
, например:
create table articles(
id int primary key,
description varchar(100),
extension varchar(50)
)
К сожалению, схема базы данных не может быть изменена.
Я хотел бы отобразить эту таблицу на гибкую сущность, подобную этой:
public class Article
{
public virtual int Id { get; set; }
public virtual string Description { get; set; }
public virtual IDictionary<string, object> Plugins { get; set; }
}
Каждый плагин, расширяющий Article
, отображает свои столбцы в отдельном элементе словаря.
Например, Plugin1 определяет:
public class Plugin1Entity
{
public virtual string Extension { get; set; }
}
Столбцы id
и description
принадлежат базовому приложению, тогда как extension
определяется и управляется плагином.
Когда я читаю статью, я хотел бы получить объект вроде:
new Article
{
Id = 12,
Description = "some description",
Plugins = new Dictionary<string, object>
{
["Plugin1"] = new Plugin1
{
Extension = "some value"
}
}
}
Плагины динамически загружаются с помощью MEF, поэтому я не могу ссылаться на Plugin1Entity
непосредственно из класса Article
. Также у меня не может быть свойства в Article
для плагинов, так как они известны только во время выполнения: вот почему мы хотели бы иметь это Dictionary
.
В идеале сопоставления - это что-то вроде:
public class ArticleMap : ClassMap<Article>
{
public ArticleMap()
{
Table("articles");
Id(i => i.Id, "id").GeneratedBy.Assigned();
Map(i => i.Description);
}
}
public class Plugin1Mapping : ComponentMap<Plugin1Entity>
{
public Plugin1Mapping()
{
Map(i => i.Extension);
}
}
Пока что мы получаем некоторые результаты, используя пользовательский IPropertyAccessor
, который динамически отображает сущность плагина в поле словаря, а не в свойстве Article
.
Как я могу сопоставить такую модель? Существуют ли другие возможные способы динамического расширения базового объекта с помощью полей, определенных в другой сборке?