在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);
}
}