用自己的类型和表达式调用Select。

huangapple go评论59阅读模式
英文:

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 = &quot;FullName&quot;;
var type = typeof(Contact);
var xpQueryType = typeof(XPQuery&lt;&gt;).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&lt;&gt;).MakeGenericType(type),
                        typeof(Expression&lt;&gt;).MakeGenericType(genericType)
                    });
var query = selectMethod.Invoke(null, new[] { xpQueryInstance, condition }) as IQueryable&lt;string&gt;;
var r = query.Distinct().ToList();

但我无法正确获取 select 方法以调用它。它返回 null 或引发不同的异常(模糊匹配等)。
我如何才能实现这个?

英文:

I want to done follow:

var xpQuery = new XPQuery&lt;Contact&gt;(session);
var select = xpQuery.Select(s =&gt; 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 = &quot;FullName&quot;;
var type = typeof(Contact);
var xpQueryType = typeof(XPQuery&lt;&gt;).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&lt;&gt;).MakeGenericType(type),
									typeof(Expression&lt;&gt;).MakeGenericType(genericType)
								});
var query = selectMethod.Invoke(null, new[] { xpQueryInstance, condition }) as IQueryable&lt;string&gt;;
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(&quot;FullName&quot;).ToList();

And methods realisation:

public static class QueryableExtensions
{
    public static IQueryable&lt;TValue&gt; Select&lt;TValue&gt;(this IQueryable query, string propName)
    {
        var entityParam = Expression.Parameter(query.ElementType, &quot;e&quot;);
        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&lt;TValue&gt;(queryExpression);
    }

    public static IQueryable&lt;TValue&gt; SelectDistinct&lt;TValue&gt;(this IQueryable query, string propName)
    {
        return query.Select&lt;TValue&gt;(propName).Distinct();
    }		
    
    public static IQueryable&lt;string&gt; SelectDistinct(this IQueryable query, string propName)
    {
        return query.SelectDistinct&lt;string&gt;(propName);
    }
};

huangapple
  • 本文由 发表于 2023年5月31日 23:00:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76374873.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定