General constraints and type evaluation of an expression

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

I have something like this.

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

      

The details are EntityBase

not important.

I originally wrote this extension method for storing DRY stuff:

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

      

I would call it like this:

modelBuilder.Entity<Foo>.WithKeywords();

      

However, the Entity Framework or the C # compiler treats e

the lambda as IKeywordedEntity

not TEntityType

. This spawns the Entity Framework.

Knowing this, I experimented with manually writing lambda Expression

for both 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();
}

      

IntelliSense now correctly shows me the combination of EntityBase

and IKeywordedEntity

and and tells me that e

- TEntityType

.

My question is, why does a passed / compiled expression tree from a lambda treat e

like IKeywordedEntity

and not TEntityType

?

+1


source to share


1 answer


I'm not an expert on expressions and Lambdas, but this is what I think is going on.

When we just specify a lambda to convert it to an expression tree, the compiler does the job of converting things to a tree. In the body of the method, all the compiler can see is IKeyworkedEntity.Keywords

not TEntityType.Keywords

and it uses the explicit property name ie uses the following



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

      

This is causing the problem we see. Now, if we build the expression tree ourselves, we know that TEntityType

there is a property in, and we talk about it in the tree. This leads to migration as it sees the property on the class and not on the interface.

0


source







All Articles