代码之家  ›  专栏  ›  技术社区  ›  CJH

从一个IQueryable<T>获取选定的T属性到IQueryable<MyClass>

  •  3
  • CJH  · 技术社区  · 6 年前

    我有一个包含 IQueryable<T> 其中每一行包含一个具有一组属性的类的实例。

    我有另一个类(MyClass)与上面的类T有一些相同的属性即相同的名称和数据类型。

    我还有一个字符串列表,其中包含两个类之间共享的属性名。

    我想创造一个新的 IQueryable<myClass> 其中myClass实例属性用原始文件中的名称清酒属性填充 可液化<t>

    这有道理吗?请让我知道,如果我能提供更多的信息或使任何更清楚。

    编辑 我将尝试添加一些代码来更好地说明我知道这里有无数的缺点,包括增加了一个可液化的-但这是为了说明:

    IQueryable<T> qry = this.GetSomeDataIntoIQueryable();
    
    // Just getting a list of the Shared Property Names between the two classes
    List<string> sharedProprtyNames = new List<string>();
    foreach (var item in ListofSharedPropertyNames)
    {
        sharedProprtyNames .Add(item.SharedPropertyName);
    }
    
    IQueryable<myClass> myClassIQ;
    foreach(var classItem in qry)
    {
        myClass x = new myClass();
        foreach(var sharedProperty in sharedProprtyNames )
        {
            myClass[sharedProperty] = classItem[sharedProperty];
        }
        myClassIQ.Add(myClass);
    }
    
    2 回复  |  直到 6 年前
        1
  •  4
  •   Marc Gravell    6 年前

    类似:

    static IQueryable<TTo> Select<TFrom, TTo>(
         this IQueryable<TFrom> source,
         params string[] members)
    {
        var p = Expression.Parameter(typeof(TFrom));
        var body = Expression.MemberInit(
            Expression.New(typeof(TTo)),
            members.Select(member => Expression.Bind(
                typeof(TTo).GetMember(member).Single(),
                Expression.PropertyOrField(p, member))));
    
        var lambda = Expression.Lambda<Func<TFrom, TTo>>(body, p);
        return source.Select(lambda);
    }
    

    ?

    这将创建 IQueryable<T> -友好投影 TFrom TTo ,尊重来自 members .

    在你的例子中,应该是:

    IQueryable<myClass> myClassIQ = qry.Select<T, myClass>(ListofSharedPropertyNames);
    

    (在数组/列表之间调整 成员 参数以满足您的方便-因为我们使用 Select ,两者都适用)

        2
  •  3
  •   xanatos    6 年前

    使用 System.Linq.Dynamic.Core 你可以:

    IQueryable<Table1> query1 = ...
    var res = query.Select<SubTable1>("new(" + string.Join(",", new[] { "Col1", "Col2" }) + ")").ToArray();
    

    在哪里? query1 是你的问题, Table1 T 关于你的问题, SubTable1 MyClass 我是说, "Col1", "Col2" 是必须选择的列。

    你可以不用 system.linq.dynamic.core系统 库并简单地构建一个表达式树…但这是一种痛苦:-)

    我的汉斯·帕桑密码变体:

    public static IQueryable<TResult> Select<TSource, TResult>(this IQueryable<TSource> source, IEnumerable<string> columns)
    {
        // the x in x => ...
        var par = Expression.Parameter(typeof(TSource), "x");
    
        // "Bindings" (the Col1 = x.Col1 inside the x => new { Col1 = x.Col1 })
        var binds = columns.Select(x => Expression.Bind((MemberInfo)typeof(TResult).GetProperty(x) ?? typeof(TResult).GetField(x), Expression.PropertyOrField(par, x)));
    
        // new TResult
        var new1 = Expression.New(typeof(TResult));
    
        // new TResult { Bindings }
        var mi = Expression.MemberInit(new1, binds);
    
        // x => new TResult { Bindings }
        var lambda = Expression.Lambda<Func<TSource, TResult>>(mi, par);
    
        // Select(x => new TResult { Bindings })
        return source.Select(lambda);
    }
    

    (几乎完全等同于……唯一不同的是他用 GetMember() 当我使用 GetProperty() + GetField() )