将几个类似的SELECT表达式Expression <func <t,object =“” >>组合成一个表达式

时间:2019-03-29 10:51:32

标签: c# entity-framework linq iqueryable

Combine several similar SELECT-expressions into a single expression上回复

我修改了以下代码,并正常工作。.

但是我想使用类似的表达式

Expression<Func<Agency, object>> selector1 = x => new { Name = x.Name };

代替

Expression<Func<Agency, AgencyDTO>> selector1 = x => new AgencyDTO { Name = x.Name };

如何使它与此类匿名类型一起使用?

如果使用匿名类型,则此代码(MemberInitExpression)selector.Body会中断

----当前代码---

public static class SelectBuilder
{

     public static IQueryable<object> SelectExtend<TSource>(this IQueryable<TSource> queryable, params Expression<Func<TSource, object>>[] selectors) => queryable.Select(Combine(selectors)); //Won't work

    public static IQueryable<TResult> SelectExtend<TSource, TResult>(this IQueryable<TSource> queryable, params Expression<Func<TSource, TResult>>[] selectors) => queryable.Select(Combine(selectors));

    private static Expression<Func<TSource, TDestination>> Combine<TSource, TDestination>(params Expression<Func<TSource, TDestination>>[] selectors)
    {
        var expression = Expression.Parameter(typeof(TSource), "s");
        return Expression.Lambda<Func<TSource, TDestination>>(
            Expression.MemberInit(
                Expression.New(typeof(TDestination).GetConstructor(Type.EmptyTypes) ?? throw new InvalidOperationException()), selectors.Select(selector => new
                {
                    selector,
                    replace = new ParameterVisitorReplacer(selector.Parameters[0], expression)
                })
                    .SelectMany(t => ((MemberInitExpression)t.selector.Body).Bindings.OfType<MemberAssignment>(), (t, binding) => Expression.Bind(binding.Member, t.replace.VisitAndConvert(binding.Expression, "Combine") ?? throw new InvalidOperationException()))), expression);
    }

    private sealed class ParameterVisitorReplacer : ExpressionVisitor
    {
        private readonly ParameterExpression _to;
        private readonly ParameterExpression _from;

        public ParameterVisitorReplacer(ParameterExpression from, ParameterExpression to)
        {
            _to = to;
            _from = from;
        }

        protected override Expression VisitParameter(ParameterExpression node) => node == _from ? _to : base.VisitParameter(node);
    }

}

0 个答案:

没有答案