通用约束和表达式类型评估

时间:2012-03-28 12:03:23

标签: c# .net lambda

这是基于我之前的一个问题: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();
}

现在,智能感知正在向我展示EntityBaseIKeywordedEntity的组合,并告诉我eTEntityType

我的问题是:为什么来自lambda的传递/编译表达式树将e视为IKeywordedEntity,而不是TEntityType

1 个答案:

答案 0 :(得分:0)

我不是Expressions和Lambdas的专家,但这是我的想法。

当我们只指定一个lambda将其转换为表达式树时,编译器会完成将事物转换为树的工作。在方法体中,所有编译器都可以看到IKeyworkedEntity.Keywords而不是TEntityType.Keywords并且它使用显式属性名称,即使用以下

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

这导致我们看到的问题。现在,如果我们自己构建表达式树,我们知道TEntityType上有一个属性,我们在树中就这么说了。这会导致迁移通过,因为它在类上而不是在接口上看到属性。

相关问题