How can I cast an expression from type interface,

2019-05-30 15:06发布

问题:

In my interface I have following defined

List<IFoo> GetListOfFoo<T>(Expression<Func<T, bool>> predicate) where T : IFoo;

In my implementation I'll cast the expression in the specific type:

if (typeof(T) == typeof(Foo))
{
    Expression converted = Expression.Convert(predicate.Body, typeof(Foo));
    Expression<Func<Foo, bool>> newPredicate = 
        Expression.Lambda<Func<Foo, bool>>(converted, predicate.Parameters);
}

I try to use my implementation like this:

Expression<Func<Foo, bool>> predicate = c => c.Name == "Myname";
_repository.GetListOfFoo<Foo>(predicate);

I get no compiling errors, but if I use this, I get an Exception that in the ExpressionBody is the bool argument defined.

Where is my problem?

回答1:

Your code doesn't make any sense.

You're creating an Expression.Convert that returns a Foo, then trying to use that as a function that returns a bool.

The Expression.Convert also doesn't make sense; you can't convert a bool to a Foo.

You're probably trying to write

var converted = (Expression<Func<Foo, bool>>) predicate;

As long as T is Foo, this will work fine.



回答2:

The parameter's type need to change, not the body of the expression.

Upon invocation from your implementation, you would have to do the conversion.

Also does not make sense why you need this as Foo : IFoo.



回答3:

I found a better solution. I don't need to cast the predicate themselves.

public List<IFoo> GetFoos<T>(Expression<Func<T, bool>> predicate) where T : class, IModel 
{
    var result = new List<IFoo>();
    var repository = new Repository<T>();
    result.AddRange(repository.GetEntities(predicate).ToList().ConvertAll(c => (IFoo)c));
    return result;
}