如何转换Expression <func <t,object =“”>&gt;表达式<func <t,bool =“”>&gt;?</func <t,> </func <t,>

时间:2015-01-20 08:43:32

标签: c# .net

我可以找到很多关于如何更改表达式主体的信息,但是我找不到有关如何更改ReturnType的信息。

以下是我编写的代码,其中包含对下面给出的Convert例程的调用。

    private T[] CheckCreatedOnDate<T>(Expression<Func<T, object>> fieldExpression, T[] input, Data.Context context) where T : Entity
    {
        var fieldDelegate = fieldExpression.Compile();

        Expression<Func<T, bool>> predicateExpression = Convert(fieldExpression);  
        Func<T, bool> predicateDelegate = predicateExpression.Compile();
        Predicate<T> predicate = predicateDelegate.Invoke;

        DbSet<T> dbSet = context.Set<T>();
        var data = dbSet.ToList();

        foreach (T inputRecord in input)
        {
            var fieldObject = fieldDelegate.Invoke(inputRecord);

            var dataRecord = data.SingleOrDefault(x => Equals(predicate, fieldObject));

            if (dataRecord != null)
            {
                inputRecord.CreatedOn = dataRecord.CreatedOn;
            }
        }

        return input;
    }

此方法的行为应与EF中的AddOrUpdate方法非常相似,但是如果记录已经在Db中,则此方法只会替换createdOn日期。

但是我的代码仍无效。创建的谓词似乎不正确,因为它永远不会在Db中找到相关记录。

非常感谢。

干杯迈克

1 个答案:

答案 0 :(得分:0)

假设fieldExpression类似于(T e) => e.Field,我得出结论,您希望在Field列中找到具有相同值的DB记录。

试试这个:

foreach (T inputRecord in input)
{
    object fieldObject = fieldDelegate.Invoke(inputRecord);

    ParameterExpression p = fieldExpression.Parameters.First();
    // Equivalent to x => x.Field == fieldObject
    Expression<Func<T, bool>> predicate = Expression.Lambda<Func<T, bool>>(
        // input.Field == fieldObject
        Expression.Equal(
            // input.Field
            fieldExpression.Body,
            // constant from fieldObject
            Expression.Constant(fieldObject)
        ),
        new []{ p }
    );

    T dataRecord = dbSet.SingleOrDefault(predicate);

    if (dataRecord != null)
    {
        inputRecord.CreatedOn = dataRecord.CreatedOn;
    }
}

我通过获取fieldExpression正文并将其传递给SingleOrDefault调用,在每个循环运行中创建全新的谓词。