如何构建这个复杂的Expression Func?

时间:2017-02-04 12:51:47

标签: c# entity-framework lambda expression

我目前正在import java.util.Map; import java.util.TreeMap; public class Test { public static void main( String[] args ) { Map<String, Integer> playersList = new TreeMap<>(); playersList.put( "Michael", 2000 ); playersList.put( "Mark", 900 ); playersList.put( "Halk", 800 ); playersList.put( "Albion", 700 ); playersList.put( "Cristine", 600 ); playersList.put( "Emma", 500 ); playersList.put( "Prince", 400 ); playersList.put( "Jason", 300 ); playersList.put( "Tim", 200 ); playersList.put( "Bob", 100 ); playersList.put( "Jackson", 50 ); playersList.forEach( ( playerName, points ) -> { printMethod( playerName, points, calculatePosition( points ) ); } ); } public static void printMethod( String playerName, int point, int position ) { System.out.println( "Player name is " + playerName + " Point was " + point + " and player position " + position ); } public static int calculatePosition( int points ) { int position = 4; if ( points > 1000 ) { position = 1; } else if ( points > 500 && points < 1000 ) { position = 2; } else if ( points > 100 && points < 400 ) { position = 3; } return position; } } 网站上工作,我有这个数据库对象:

EF

一个Item类:

public partial class Association
{
    public Association()
    {
        this.Users = new HashSet<User>();
    }

    public Guid Id { get; set; }
    public Guid ItemId { get; set; }

    [ForeignKey("ItemId")]
    public virtual Item Item { get; set; }

    [InverseProperty("Association")]
    public virtual ICollection<User> Users { get; set; }
}

这本词典:

public partial class Item
{
    public Item()
    {
        this.Associations = new HashSet<Association>();
    }

    public Guid Id { get; set; }
    public ItemTypeEnum Type { get; set; }

    [InverseProperty("Item")]
    public virtual ICollection<Association> Associations { get; set; }
}

如果public static Dictionary<ItemTypeEnum, int> MaxOccupationRange = new Dictionary<ItemTypeEnum, int>() { { ItemTypeEnum.Type1, 1 }, { ItemTypeEnum.Type2, 2 }, { ItemTypeEnum.Type3, 5 }, { ItemTypeEnum.Type4, 10 }, }; 我需要Expression<Func<Association, bool>> true,我需要association.Users.Count < MaxOccupationRange[association.Item.Type]。 我认为这应该大致类似于以下方法,但不幸的是,我对false概念不够熟悉,无法实现这一目标。

调试以下结果时,似乎计算(未优化但是)正确的表达式。

Expression

我试着这样称呼它:

public static Expression<Func<TSource, bool>> MyExprMethod<TSource, TKey, TKey2, TValue>(Expression<Func<TSource, TKey>> source, Expression<Func<TSource, TKey2>> source2, IReadOnlyDictionary<TKey, TValue> dict)
    {
        var body = dict
            .Aggregate((Expression)null, (next, dicEntry) => next == null
                ? Expression.Condition
                    (
                        Expression.LessThan(source2.Body, Expression.Constant(dicEntry.Value)),
                        Expression.Constant(true),
                        Expression.Constant(false)
                    )
                : Expression.Condition
                    (
                        Expression.Equal(source.Body, Expression.Constant(dicEntry.Key)),
                        Expression.Condition
                        (
                            Expression.LessThan(source2.Body, Expression.Constant(dicEntry.Value)),
                            Expression.Constant(true),
                            next
                        ),
                        next
                    )
                );

        return Expression.Lambda<Func<TSource, bool>>(body, source.Parameters[0]);
    }

但显然它抱怨var expr = MyHelper.MyExprMethod((Association x) => x.Item.Type, (Association b) => b.Users.Count, Item.MaxOccupationRange); 参数未被分配,因为它没有出现在结果lambda中。
我尝试了很多东西(匿名类型而不是两个来源等),但似乎我对这个概念不太熟悉,我找不到生成这种表达式的方法。

请有人给我看看吗?

非常感谢。

修改

这里是呼叫上下文:

b

此处显示的信息显示在最后一行(ToPagedList):var filter = PredicateUtils.True<Association>(); var expr = MyHelper.MyExprMethod((Association x) => x.Item.Type, (Association b) => b.Users.Count, Item.MaxOccupationRange); filter = filter.And(expr); var associations = entities.Associations.Where(filter); return associations .OrderBy(a => a.Id).ToPagedList(pageNb, 2);

1 个答案:

答案 0 :(得分:1)

我猜你需要re-parametrize第二个表达式

    public static Expression<Func<TSource, bool>> MyExprMethod<TSource, TKey, TKey2, TValue>(Expression<Func<TSource, TKey>> source, Expression<Func<TSource, TKey2>> source2, IReadOnlyDictionary<TKey, TValue> dict)
    {
        source2 = PredicateRewriter.Rewrite(source2, source.Parameters[0]);
        var body = dict

通过帮助者

    public class PredicateRewriter
    {
        public static Expression<Func<T, U>> Rewrite<T,U>(Expression<Func<T, U>> exp, //string newParamName
            ParameterExpression param)
        {
            //var param = Expression.Parameter(exp.Parameters[0].Type, newParamName);
            var newExpression = new PredicateRewriterVisitor(param).Visit(exp);

            return (Expression<Func<T, U>>)newExpression;
        }

带有访客模式

        private class PredicateRewriterVisitor : ExpressionVisitor
        {
            private readonly ParameterExpression _parameterExpression;

            public PredicateRewriterVisitor(ParameterExpression parameterExpression)
            {
                _parameterExpression = parameterExpression;
            }

            protected override Expression VisitParameter(ParameterExpression node)
            {
                return _parameterExpression;
            }
        }
    }