我目前正在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);
答案 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;
}
}
}