通用的约束和Ex pression型式评价型式、评价、Ex、pression

2023-09-06 18:03:18 作者:1心為忘記”

这是基于previous的问题,我有: EF code首先实现的接口属性

This is based on a previous question I had: EF Code First implemented interface property

我有这样的事情。

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

的细节 EntityBase 并不重要。

起初,我写了这个扩展方法使事情干:

Initially I wrote this extension method to keep things DRY:

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

我会调用它,就像这样:

I would invoke it like so:

modelBuilder.Entity<Foo>.WithKeywords();

然而,实体框架或C#编译器是治疗电子中的λ为 IKeywordedEntity 不是 TEntityType 。这个怪胎实体框架。

However, Entity Framework or the C# compiler is treating e in the lambda as IKeywordedEntity not TEntityType. This freaks out Entity Framework.

知道了这一点,我尝试用手工编写的拉姆达为防爆pression 的hasMany 。我想出了以下内容:

Knowing this, I experimented with manually writing the lambda as an Expression for HasMany. I came up with the following:

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 正确地向我展示的结合,告诉我,ê TEntityType

Now the IntelliSense is showing me the combination of EntityBase and IKeywordedEntity correctly and telling me that e is TEntityType.

我的问题是:为什么从拉姆达治疗传递/编译EX pression树电子 IKeywordedEntity ,不是 TEntityType

My question is: why does the passed/compiled expression tree from the lambda treat e as IKeywordedEntity, not TEntityType?

推荐答案

我在防爆pressions和lambda表达式方面的专家,但是这就是我的想法是怎么回事。

I'm no expert on Expressions and Lambdas, but this is what I think is going on.

当我们只需指定一个lambda将其转换为一个前pression树,编译器做转换的东西树的工作。在法身上所有的编译器可以看到的是 IKeyworkedEntity.Keywords 不是 TEntityType.Keywords ,它使用了明确的属性名即使用以下

When we just specify a lambda to convert it to an expression tree, the compiler does the work of converting things to the tree. In the method body all the compiler can see is IKeyworkedEntity.Keywords not TEntityType.Keywords and it uses the explicit property name i.e. uses the following

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

这是造成我们看到的问题。现在,如果我们所建立的前pression树自己,我们知道有一个属性 TEntityType ,我们在树中这样说。这会导致迁移,因为它看到了财产类而不是一个接口上通过。

That is causing the issue which we see. Now if we build the expression tree ourselves, we know that there is a property on the TEntityType and we are saying so in the tree. This causes the migration to go through since it sees the property on a class and not on an interface.