英文:
Call Select with own type and expression
问题
Here's the translation of your provided text:
我想完成以下操作:
var xpQuery = new XPQuery<Contact>(session);
var select = xpQuery.Select(s => s.FullName);
var distinct = select.Distinct();
var list = distinct.ToList();
XPQuery 是 IQueryable<T>,所以我想请求指定属性值的不同列表,但 Contact 和 FullName 应该是变量。
所以我正在做以下操作:
var propertyName = "FullName";
var type = typeof(Contact);
var xpQueryType = typeof(XPQuery<>).MakeGenericType(type);
var xpQueryInstance = Activator.CreateInstance(xpQueryType, new object[] { session });
var param = Expression.Parameter(type);
var genericType = Expression.GetFuncType(type, typeof(string));
var condition = Expression.Lambda(genericType, Expression.Property(param, propertyName), param);
var selectMethod = typeof(Queryable).GetMethod(
nameof(Queryable.Select),
new Type[]
{
typeof(IQueryable<>).MakeGenericType(type),
typeof(Expression<>).MakeGenericType(genericType)
});
var query = selectMethod.Invoke(null, new[] { xpQueryInstance, condition }) as IQueryable<string>;
var r = query.Distinct().ToList();
但我无法正确获取 select 方法以调用它。它返回 null 或引发不同的异常(模糊匹配等)。
我如何才能实现这个?
英文:
I want to done follow:
var xpQuery = new XPQuery<Contact>(session);
var select = xpQuery.Select(s => s.FullName);
var distinct = select.Distinct();
var list = distinct.ToList();
XPQuery is IQueryable<T> so I want to request the distinct list of specified property values, but Contact and FullName should be variables here.
So I'm doing follow:
var propertyName = "FullName";
var type = typeof(Contact);
var xpQueryType = typeof(XPQuery<>).MakeGenericType(type);
var xpQueryInstance = Activator.CreateInstance(xpQueryType, new object[] { session });
var param = Expression.Parameter(type);
var genericType = Expression.GetFuncType(type, typeof(string));
var condition = Expression.Lambda(genericType, Expression.Property(param, propertyName), param);
var selectMethod = typeof(Queryable).GetMethod(
nameof(Queryable.Select),
new Type[]
{
typeof(IQueryable<>).MakeGenericType(type),
typeof(Expression<>).MakeGenericType(genericType)
});
var query = selectMethod.Invoke(null, new[] { xpQueryInstance, condition }) as IQueryable<string>;
var r = query.Distinct().ToList();
But I cannot correctly get select method to Invoke it. It returns null or throw different exceptions (ambigiuos match and so on).
How can I achieve this?
答案1
得分: 1
实际上,您只需要动态的 `Select`,其他方法可以保持通用。
方法实现如下:
```cs
public static class QueryableExtensions
{
public static IQueryable<TValue> Select<TValue>(this IQueryable query, string propName)
{
var entityParam = Expression.Parameter(query.ElementType, "e");
Expression propExpression = Expression.Property(entityParam, propName);
if (propExpression.Type != typeof(TValue))
propExpression = Expression.Convert(propExpression, typeof(TValue));
var selector = Expression.Lambda(propExpression, entityParam);
var queryExpression = query.Expression;
queryExpression = Expression.Call(typeof(Queryable), nameof(Queryable.Select),
new[] { query.ElementType, typeof(TValue) }, queryExpression, Expression.Quote(selector));
return query.Provider.CreateQuery<TValue>(queryExpression);
}
public static IQueryable<TValue> SelectDistinct<TValue>(this IQueryable query, string propName)
{
return query.Select<TValue>(propName).Distinct();
}
public static IQueryable<string> SelectDistinct(this IQueryable query, string propName)
{
return query.SelectDistinct<string>(propName);
}
};
英文:
Actully you need only dynamic Select
, other methods can be just generic
var list = xpQuery.SelectDistinct("FullName").ToList();
And methods realisation:
public static class QueryableExtensions
{
public static IQueryable<TValue> Select<TValue>(this IQueryable query, string propName)
{
var entityParam = Expression.Parameter(query.ElementType, "e");
Expression propExpression = Expression.Property(entityParam, propName);
if (propExpression.Type != typeof(TValue))
propExpression = Expression.Convert(propExpression, typeof(TValue));
var selector = Expression.Lambda(propExpression, entityParam);
var queryExpression = query.Expression;
queryExpression = Expression.Call(typeof(Queryable), nameof(Queryable.Select),
new[] { query.ElementType, typeof(TValue) }, queryExpression, Expression.Quote(selector));
return query.Provider.CreateQuery<TValue>(queryExpression);
}
public static IQueryable<TValue> SelectDistinct<TValue>(this IQueryable query, string propName)
{
return query.Select<TValue>(propName).Distinct();
}
public static IQueryable<string> SelectDistinct(this IQueryable query, string propName)
{
return query.SelectDistinct<string>(propName);
}
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论