如何将Expression<Func<BaseClass, bool>>转换为Expression<Func<InheritedClass, bool>>?

3
假设我有一个基类和继承类。
public class BaseClass
{
    public String SystemName { get; set; }
    public String UserName { get; set; }
}

internal class InheritedClass : BaseClass
{
    public Guid Id { get; set; }        
}

我的模块从外部接收到了一些基类的表达式(但该继承类在这里是不可见的)。

Expression<Func<BaseClass, bool>>

它描述了一些过滤逻辑,例如如下所示:
Expression<Func<BaseClass, bool>> filter = x => x.SystemName.StartsWith("ABC") && x.UserName != ""

但是在我的模块内部,我需要使用

Expression<Func<InheritedClass, bool>>

因为我将这个过滤器应用到了IQueryable上,就像这样

IQueryable<InheritedClass> filteredItems = Items.Where(filter);

派生类具有基类的所有属性 - 因此,我的经验不太丰富的头脑认为转换是可能的 :)

是否有将传递的表达式转换为我所需要的方式?

谢谢。


谢谢。我不知道正确的搜索短语 :) - bairog
1个回答

0
请使用这个实用类。
public static class Utility
{
    //public static IEnumerable<TTarget> Where<TSource, TTarget>(this IEnumerable<TSource> source, Expression<Func<TSource, bool>> predicate) where TTarget : class, TSource
    //{
    //     return source.Where(obj => obj is TTarget).Where(predicate.Compile()).Select(obj => obj as TTarget);
    //}

    public static IQueryable<TTarget> Where<TSource, TTarget>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate) where TTarget : class, TSource
    {
        return source.Where(obj => obj is TTarget).Where(predicate).Select(obj => obj as TTarget);
    }
}

例子就像这样, 超类和子类

class Person
{
    public String Name { get; set; }
    public ushort Age { get; set; }
}

class Student : Person
{
    public String StudentId { get; set; }
}

class Teacher : Person
{
    public String TeacherId { get; set; }
}

使用该工具并进行测试

            /*List of Persons*/
            List<Person> persons = new List<Person>()
                                                          {
                                                              new Student(){StudentId = "Std-01", Name = "Roy", Age = 24},
                                                              new Student(){StudentId = "Std-02", Name = "Jhon", Age = 25},
                                                              new Teacher(){TeacherId = "Tch-01", Name = "Roy", Age = 24},
                                                              new Teacher(){TeacherId = "Tch-02", Name = "Jhon", Age = 25}
                                                          };
            /*predictions*/
            Expression<Func<Person, bool>> prediction = x => x.Name.Contains("o");


            /*Use the utility*/
                                                                    /*Get Teacher from Persons*/
            IQueryable<Teacher> filteredItems = persons.AsQueryable().Where<Person, Teacher>(prediction);
            List<Teacher> result = filteredItems.ToList();

结果将会得到TeacherId为"Tch-01"和"Tch-02"的老师

虽然我使用的是IEnumerable而不是IQueryable,但希望这会有所帮助


它很可能应用于IQueryable,原因通常是表达式被翻译成SQL或类似的语言,因此调用compile可能会违背意图。 - Rune FS
@Rune FS:我原以为意图是使用提供的Expression<fun<SuperClass>, bool>从List<SuperClass>中获取List<SubClass>,因此制作了这样的示例。但似乎主要过程要求将Expression<fun<SuperClass>, bool>转换为Expression<fun<SubClass>>,因此对误解感到抱歉。 - Dipon Roy
嗯,那不是一个问题,但似乎这是一场毫无意义的讨论。该问题已关闭,因为它已经得到了回答,我们正在就一个与已回答的问题不符的答案进行辩论。 - Rune FS
@Rune FS:请不要把这当作辩论,我只是在尝试提供一个解决方案……我已经将IEnumerable更改为IQueryable。您的建议将永远受到重视。 - Dipon Roy
让我们在聊天中继续这个讨论。点击此处进入聊天室 - Dipon Roy
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接