说我有以下内容。
foreach (var loop in helper.Loop(x => x.LoopItems))
{
loop.Text(x => x.Name);
loop.Span(x => x.Name);
foreach (var loopItem in loop.Loop(x => x.NestedLoopItems))
{
loopItem.Text(x => x.Age);
}
}
这只能用我当前的实现创建,但它必须编译内部lambda表达式的次数与循环项一样多。目前,这样做可以创建表达式来访问List<T>
索引器。例如。 x.ListItems[i]
var methodCallExpression = Expression.Call(_expression, ((PropertyInfo) _expression.Member).PropertyType.GetMethod("get_Item"), Expression.Constant(i));
var expression = Expression.Lambda<Func<TModel, T>>(methodCallExpression, _expression.GetParameter<TModel>());
然后呢
var newExpression = CombineExpression(listExpression);
var enumerable = newExpression.Compile().Invoke(_htmlHelper.ViewData.Model);
这是编译步骤似乎是昂贵的。
是否有任何方法可以缓存这个,因为它需要为每个循环创建一个新的,这样i
中的Expression.Constant(i)
每次修改表达式时都需要递增。
答案 0 :(得分:1)
我不知道CombineExpression的功能,但是如果你可以从Func<TModel, T>
更改为Func<TModel, int, T>
(假设索引器总是一个int),那么你可以在这个方法中添加另一个泛型你已经过去了&#34;我&#34;获取表达式中的常量。
也不完全确定_expression的类型是什么,所以我不知道这是否正在调用我认为的重载。
var parameterExpression = Expression.Parameter(typeof(int), "i");
var methodCallExpression = Expression.Call(_expression, ((PropertyInfo) _expression.Member).PropertyType.GetMethod("get_Item"), parameterExpression);
var expression = Expression.Lambda<Func<TModel, int, T>>(methodCallExpression, _expression.GetParameter<TModel>(), parameterExpression);
然后你可以编译表达式并获得Func<TModel, int, T>
,并且在调用Func时你会传入&#34; i&#34;值。
同样,因为我不知道CombineExpression的作用,但是如果你从中得到一个强类型的Func,你可以在没有调用的情况下调用它。
另一方面注意为什么表达式可以访问列表索引器?为什么不使用IEnumerable&lt;&gt;如果你不知道他们输入但是需要将对象强制转换为IEnumerable(非泛型)并迭代它,那么还是最差的演员?