【问题标题】:Creating generic Expression创建通用表达式
【发布时间】:2013-09-20 18:28:05
【问题描述】:

我对泛型表达式有疑问。

我有一个Expression<Func<T, bool>>,我想将Expression<Func<T, bool>> 转换为Expression<Func<Y, bool>>T 类的对象与 Y 类具有相同的属性。

有人知道怎么解决吗?

【问题讨论】:

  • 您的两种基本方法是遍历表达式的树并重新创建一个类似的表达式,但 T 的所有用法都替换为 Y,或者您可以接受 Expression<Func<Y, T>>并调用它以及另一个表达式,并使用该组合来创建最终表达式。
  • 如果它们具有相同的属性,为什么不使用继承呢?这应该可以立即解决问题。
  • 更好的是,一个界面。
  • @meilke OP 可能无法修改 T、Y 或两者。

标签: c# generics lambda expression


【解决方案1】:

执行此操作的“首选”方法是使用包含您关心的属性的接口。

interface IMyProp
{
    string SomeProp {get;}
}

class T : IMyProp
{
    public string SomeProp 
    {
        get
        {
            //Some complicated logic
        }
    }
}

class Y : IMyProp
{
    public string SomeProp {get; set;}
}

只需将您的表达式编码为Expression<Func<IMyProp, bool>>

但是可以理解的是,您不能总是这样做,对于这种情况,您可以使用像 AutoMapper 这样的库

class T
{
    public string SomeProp 
    {
        get
        {
            //Some complicated logic
        }
    }
}

class Y
{
    public string SomeProp {get; set;}
}


//Some initiation code somewhere else in your project
public static void InitializeMappings()
{
    Mapper.CreateMap<T, Y>();
}

public static IQueryable<Y> FilterOnTAndMapToY(IQueryable<T> source, Expression<Func<T,bool>> filter)
{
      return source.Where(filter).Project().To<Y>();
}

现在这不会将您的Expression&lt;Func&lt;T, bool&gt;&gt; 完全转换为Expression&lt;Func&lt;Y, bool&gt;&gt;,但它确实允许您使用T 表达式并在应用过滤后使用它来获得Y 结果。

AutoMapper 的 Queryable Extensions 工作方式是在执行 LinqToEntities 时从 TY 的查询和转换发生在所有服务器端。所以你甚至可以做

public static IQueryable<Y> MultiFilterCast(IQueryable<T> source, Expression<Func<T,bool>> tTypeFilter, Expression<Func<Y,bool>> yTypeFilter)
{
      var filteredStage1 = source.Where(tTypeFilter);
      var castToY = filteredStage1.Project().To<Y>();
      var filteredStage2 = castToY.Where(yTypeFilter);
      return filteredStage2;
}

tTypeFilteryTypeFilter 都将在您获得结果集之前应用到服务器端。

【讨论】:

  • 如果您可以更改 T 和 Y,这可能是理想的一些变体,但是我需要与此类似的一个实例,我无法修改 T,只有 Y。
  • @lukegravitt AutoMapper 在您无法更改 T 和 Y 时效果很好。如果您不是像 OP 那样的一对一映射,那么您在调用 CreateMap&lt;T,Y&gt;() 时使用 ForMember 函数并手动进行任何不匹配的映射。
  • 这会教我不要仔细阅读整个答案! AutoMapper 看起来它实际上可能已经解决了我的问题。
  • 如果我想按 T 过滤就可以了。问题是我要过滤的源是 Y 类型。调用过滤方法的服务不知道类型( Y) 我想过滤。
猜你喜欢
  • 1970-01-01
  • 2023-03-22
  • 2018-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-01
相关资源
最近更新 更多