这是基于我之前的一个问题:EF Code First implemented interface property
我有类似的东西。
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或C#编译器将lambda中的e
视为IKeywordedEntity
而不是TEntityType
。这吓坏了实体框架。
知道了这一点,我尝试手动将lambda写为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();
}
现在,智能感知正在向我展示EntityBase
和IKeywordedEntity
的组合,并告诉我e
是TEntityType
。
我的问题是:为什么来自lambda的传递/编译表达式树将e
视为IKeywordedEntity
,而不是TEntityType
?
答案 0 :(得分:0)
我不是Expressions和Lambdas的专家,但这是我的想法。
当我们只指定一个lambda将其转换为表达式树时,编译器会完成将事物转换为树的工作。在方法体中,所有编译器都可以看到IKeyworkedEntity.Keywords
而不是TEntityType.Keywords
并且它使用显式属性名称,即使用以下
var rootExpression = Expression.Parameter(typeof (IKeyworkedEntity));
var expression = Expression.Property(rootExpression, "Keywords");
这导致我们看到的问题。现在,如果我们自己构建表达式树,我们知道TEntityType
上有一个属性,我们在树中就这么说了。这会导致迁移通过,因为它在类上而不是在接口上看到属性。