여러 C # 람다 식을 결합하는 방법 (식 >)


문제

나는 실제로 Z.EntityFramework.Plus 일괄 업데이트를 둘러싼 래퍼입니다 다음과 같은 기능을 가지고 :

    public static int UpdateBulk<T>(this IQueryable<T> query, Expression<Func<T, T>> updateFactory) where T : IBaseEntity, new()
    {
        Expression<Func<T, T>> modifiedExpression = x => new T() { ModifiedBy = "Test", ModifiedDate = DateTime.Now };
        var combine = Expression.Lambda<Func<T, T>>(
            Expression.AndAlso(
                Expression.Invoke(updateFactory, updateFactory.Parameters),
                Expression.Invoke(modifiedExpression, modifiedExpression.Parameters)
            ),
            updateFactory.Parameters.Concat(modifiedExpression.Parameters)
        );  //This returns an error

        return query.Update(combine);
    }

이렇게 호출 :

    public static int UpdateBulk<T>(this IQueryable<T> query, Expression<Func<T, T>> updateFactory) where T : IBaseEntity, new()
    {
        Expression<Func<T, T>> modifiedExpression = x => new T() { ModifiedBy = "Test", ModifiedDate = DateTime.Now };
        var combine = Expression.Lambda<Func<T, T>>(
            Expression.AndAlso(
                Expression.Invoke(updateFactory, updateFactory.Parameters),
                Expression.Invoke(modifiedExpression, modifiedExpression.Parameters)
            ),
            updateFactory.Parameters.Concat(modifiedExpression.Parameters)
        );  //This returns an error

        return query.Update(combine);
    }

여기서 IBaseEntity는 다음과 같이 정의됩니다.

    public static int UpdateBulk<T>(this IQueryable<T> query, Expression<Func<T, T>> updateFactory) where T : IBaseEntity, new()
    {
        Expression<Func<T, T>> modifiedExpression = x => new T() { ModifiedBy = "Test", ModifiedDate = DateTime.Now };
        var combine = Expression.Lambda<Func<T, T>>(
            Expression.AndAlso(
                Expression.Invoke(updateFactory, updateFactory.Parameters),
                Expression.Invoke(modifiedExpression, modifiedExpression.Parameters)
            ),
            updateFactory.Parameters.Concat(modifiedExpression.Parameters)
        );  //This returns an error

        return query.Update(combine);
    }

IBaseEntity를 구현하는 방식으로 'Problem'클래스.

UpdateBulk 함수의 updateFactory에 ModifiedBy 및 ModifiedDate를 자동으로 추가하여 UpdateBulk를 호출 할 때마다이 작업을 수행 할 필요가 없도록하고 싶습니다.

위의 UpdateBulk 함수에서 구문 분석 된 'updateFactory'표현식과 'modifiedExpression'표현식을 결합하려고했지만 오류를 반환합니다.

이진 연산자 AndAlso가 'Problem'유형에 대해 정의되지 않았습니다.

이런 식으로 병합 할 수 있습니까? 그렇다면 무엇이 잘못 되었습니까? 그렇지 않은 경우 어떻게 ModifiedBy = "Test", ModifiedDate = DateTime.Now를 updateFactory 표현식에 병합 할 수 있습니까?

고마워,로드

수락 된 답변

당신은 사용할 수 없습니다 AndAlso 하는가에 대한 의미이기 때문에, BinaryExpression - Expression<Func<T,bool>> 정의, 당신이 표현 방문자를 필요로이 경우, 여기 에서 마크 Gravell (그래서 그는 모든 신용을받을 권리)

나는 당신의 경우에, Problem class schema 의 가정과 함께 솔루션을 제공하기 위해 Linqpad 코드를 붙여 넣기를 사용하고있다.

void Main()
{
  var final = UpdateBulk((Problem p) => new Problem{CatId = 1,SubCatId = 2, ListId=3});

 // final is of type Expression<Func<T,T>>, which can be used for further processing

  final.Dump();
}

public static Expression<Func<T, T>> UpdateBulk<T>(Expression<Func<T, T>> updateFactory) where T : IBaseEntity, new()
{
    Expression<Func<T, T>> modifiedExpression = x => new T() { ModifiedBy = "Test", ModifiedDate = DateTime.Now };

    var result = Combine(updateFactory, modifiedExpression);

    return result;
}


static Expression<Func<TSource, TDestination>> Combine<TSource, TDestination>(
    params Expression<Func<TSource, TDestination>>[] selectors)
{
    var param = Expression.Parameter(typeof(TSource), "x");
    return Expression.Lambda<Func<TSource, TDestination>>(
        Expression.MemberInit(
            Expression.New(typeof(TDestination).GetConstructor(Type.EmptyTypes)),
            from selector in selectors
            let replace = new ParameterReplaceVisitor(
                  selector.Parameters[0], param)
            from binding in ((MemberInitExpression)selector.Body).Bindings
                  .OfType<MemberAssignment>()
            select Expression.Bind(binding.Member,
                  replace.VisitAndConvert(binding.Expression, "Combine")))
        , param);
}

class ParameterReplaceVisitor : ExpressionVisitor
{
    private readonly ParameterExpression from, to;
    public ParameterReplaceVisitor(ParameterExpression from, ParameterExpression to)
    {
        this.from = from;
        this.to = to;
    }
    protected override Expression VisitParameter(ParameterExpression node)
    {
        return node == from ? to : base.VisitParameter(node);
    }
}

public abstract class IBaseEntity
{
    public System.DateTime CreatedDate { get; set; }
    public string CreatedBy { get; set; }

    public System.DateTime ModifiedDate { get; set; }
    public string ModifiedBy { get; set; }

    public string DeletedBy { get; set; }
}

public class Problem : IBaseEntity
{
    public int CatId { get; set; }

    public int SubCatId { get; set; }

    public int ListId { get; set; }
}




아래 라이선스: CC-BY-SA
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.