我有一个泛型函数,其中包含一个IQueryable<T>
,其中每一行都包含具有一组属性的类的实例。
我有另一个类(MyClass),它具有与上面的类T相同的某些属性……即,相同的名称和数据类型。
我还有一个字符串列表,其中包含两个类之间共享的属性名称。
我希望能够创建一个新的IQueryable<myClass>
,在其中将myClass实例属性填充为原始IQueryable<T>
中的名称属性
这有意义吗?请让我知道我是否可以提供更多信息或使任何事情变得更清楚。
编辑 我将尝试添加一些代码以更好地说明。我知道这里有无数的错误,包括添加到IQueryable中-但这只是为了说明:
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);
}
答案 0 :(得分:4)
类似的东西:
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
的{{1}}友好投影,并尊重TTo
中的所有成员。
在您的示例中,它将是:
members
(在{/ {1}}参数的数组/列表之间进行调整,以适合您的方便-因为我们使用IQueryable<myClass> myClassIQ = qry.Select<T, myClass>(ListofSharedPropertyNames);
,所以无论哪种都可以使用
答案 1 :(得分:3)
使用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
库就可以做任何事情,而只需构建一个表达式树...但这很痛苦:-)
我的Hans Passant代码的变体:
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()
)