Как добавить DbSet‹EntityName› в контекст, который создается динамически с помощью Codedom?

Я динамически генерирую объекты с помощью Codedom. У меня также нет жестко закодированного класса контекста как части решения. То есть я также генерирую контексты во время выполнения с помощью Codedom. Я делаю это, чтобы каждый сгенерированный объект имел свой собственный контекст. У меня возникла проблема с написанием кода Codedom для класса контекста. Как часть контекста, мне нужно написать в свойстве DbSet, чтобы сгенерированный объект мог быть частью модели для контекста. В частности, мне нужна следующая строка в моем сгенерированном контексте:

public DbSet<EntityName> EntityNames { get; set; }

где EntityName — это имя созданного мной типа класса сущностей, а EntityNames — это просто имя с буквой «s» на конце. Например, я мог бы создать сущность Employee, поэтому я хотел бы сгенерировать контекст с помощью:

public DbSet<Employee> Employees { get; set; }

Для этого я пишу метод, который возвращает это свойство CodeMemberProperty. Он знает, что нужно писать Employee/Employees, потому что я передаю имя объекта. Это нормально. Метод пока выглядит так:

public static CodeMemberProperty HardCodeDbSet(string contextName)
{
    string entityName = contextName.Substring(0, contextName.Length - 7);
    CodeMemberProperty prop = new CodeMemberProperty();
    prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
    prop.Name = entityName + "s";
    prop.Type = new CodeTypeReference(typeof(DbSet<>));
    return prop;
}

Причина этой строки:

string entityName = contextName.Substring(0, contextName.Length - 7);

заключается в том, что я делаю имя сгенерированного контекста соответствующим именем сущности + «Контекст», поэтому в этой строке я удаляю «Контекст», чтобы вернуть имя сущности. Во всяком случае, это не совсем актуально. Строка, которая доставляет мне неприятности, относится к типу:

prop.Type = new CodeTypeReference(typeof(DbSet<>));

Это просто дает мне:

DbSet<>

Но мне нужно:

DbSet<EntityName>

Если я попытаюсь написать что-нибудь внутри угловых скобок, я получу сообщение об ошибке, говорящее о том, что он не может разрешить символ. Например, я хотел бы написать:

prob.Type = new CodeTypeReference(typeof(DbSet<entityType>));

И я мог бы просто сделать

Type entityType

параметр этого метода, но ему это не нравится.

Кто-нибудь знает способ обойти это? Я думал, что кодировать это будет намного проще, но Codedom не так сотрудничает, как мне иногда казалось...


person Drew    schedule 07.07.2015    source источник
comment
Зачем генерировать контекст? Взгляните на DbModelBuilder. . Также получите некоторую информацию для типов Также: Почему один контекст для каждой сущности? Чего вы хотите достичь? Какова твоя цель?   -  person user3411327    schedule 07.07.2015


Ответы (2)


Что вы в основном спрашиваете здесь, если мы перейдем к сути вопроса, так это то, как использовать отражение для получения типа закрытого универсального типа. Это не имеет никакого отношения конкретно к CodeDom или EntityFramework.

Как вы упомянули, использование typeof(DbSet<>) (или List<> или чего-либо еще) даст вам «открытый универсальный тип», то есть тот, на котором основаны конкретные общие типы. Отсюда вы можете использовать метод MakeGenericType для создания закрытого универсального типа:

var openType = typeof(DbSet<>);
var closedType = openType.MakeGenericType(entityType);
person Avner Shahar-Kashtan    schedule 07.07.2015
comment
Спасибо, что хорошо объяснили! Теперь мне ясно, о чем на самом деле шла речь. - person Drew; 07.07.2015
comment
Иногда трудно, особенно при использовании сложных библиотек, таких как CodeDom или EF, отделить лес от деревьев. :) - person Avner Shahar-Kashtan; 07.07.2015

Вам нужно взять открытый универсальный DbSet<> и сделать его закрытым, например:

typeof(DbSet<>).MakeGenericType(entityType)
person Community    schedule 07.07.2015
comment
Спасибо за помощь :) Я принял другого, потому что он был первым, ха-ха - person Drew; 07.07.2015