Общие ограничения и оценка типа выражения

62
7

Это основано на предыдущем вопросе, который у меня был: EF Code. Сначала реализовано свойство интерфейса


У меня есть что-то вроде этого.


interface IKeywordedEntity
{
ICollection<Keyword> Keywords { get; }
}
class Foo : EntityBase, IKeywordedEntity
{
public virtual ICollection<Keyword> Keywords { get { ... } }
}

Детали EntityBase не важны.


Изначально я написал этот метод расширения для хранения вещей DRY:


public static void WithKeywords<TEntityType>(this EntityTypeConfiguration<TEntityType> 
entityTypeConfiguration) where TEntityType : EntityBase, IKeywordedEntity
{
entityTypeConfiguration.HasMany(e => e.Keywords).WithMany();
}

Я бы вызвал его так:


modelBuilder.Entity<Foo>.WithKeywords();

Однако, Entity Framework или компилятор С# обрабатывают e в лямбда как IKeywordedEntity not TEntityType. Это порождает Entity Framework.


Зная это, я экспериментировал с ручной записью лямбда как Expression для HasMany. Я придумал следующее:


public static void WithKeywords<TEntityType>(this EntityTypeConfiguration<TEntityType> 
entityTypeConfiguration) where TEntityType : EntityBase, IKeywordedEntity
{
var rootExpression = Expression.Parameter(typeof (TEntityType));
var expression = Expression.Property(rootExpression, "Keywords");

entityTypeConfiguration.HasMany(Expression.Lambda<Func<TEntityType, ICollection<Keyword>>>(expression, rootExpression)).WithMany();
}


Теперь IntelliSense корректно показывает мне комбинацию EntityBase и IKeywordedEntity и говорит мне, что e - TEntityType.


Мой вопрос: почему переданное/скомпилированное дерево выражений из лямбда лечит e как IKeywordedEntity, а не TEntityType?

спросил(а) 2021-01-19T12:24:00+03:00 3 месяца, 2 недели назад
1
Решение
106

Я не эксперт по выражениям и Lambdas, но это то, что я думаю, происходит.


Когда мы просто укажем лямбда, чтобы преобразовать его в дерево выражений, компилятор выполняет работу по преобразованию вещей в дерево. В теле метода все, что может видеть компилятор, это IKeyworkedEntity.Keywords not TEntityType.Keywords и он использует явное имя свойства i.e использует следующие

var rootExpression = Expression.Parameter(typeof (IKeyworkedEntity));
var expression = Expression.Property(rootExpression, "Keywords");

Это вызывает проблему, которую мы видим. Теперь, если мы сами строим дерево выражений, мы знаем, что в TEntityType есть свойство, и мы говорим об этом в дереве. Это приводит к миграции, поскольку он видит свойство в классе, а не на интерфейсе.

ответил(а) 2021-01-19T12:24:00+03:00 3 месяца, 2 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема