Ответ 1
Вы комбинируете a => a == 3
и a => a == 4
в (a => a == 3) || (a => a == 4)
, но вместо этого вы должны сделать это a => (a == 3 || a == 4)
. Это не слишком сложно сделать вручную, но кто-то сделал это уже для вас. Найдите "Сочетание выражений".
Изменить: по запросу простой пример того, как это сделать вручную.
Изменить 2: он использует ExpressionVisitor
, который является новым для .NET 4, но в MSDN вы можете найти полезную реализацию для более ранних версий. Я предполагаю, что код MSDN не квалифицируется как "сторонний" для ваших целей. Вам нужно только изменить метод protected virtual Expression Visit(Expression exp)
на public
. И поскольку Enumerable.Zip
недоступен для вас, и он не нужен, он ушел сейчас.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
namespace DemoApp
{
<include ExpressionVisitor definition here for .NET 3.5>
public class ExpressionParameterReplacer : ExpressionVisitor
{
public ExpressionParameterReplacer(IList<ParameterExpression> fromParameters, IList<ParameterExpression> toParameters)
{
ParameterReplacements = new Dictionary<ParameterExpression, ParameterExpression>();
for (int i = 0; i != fromParameters.Count && i != toParameters.Count; i++)
ParameterReplacements.Add(fromParameters[i], toParameters[i]);
}
private IDictionary<ParameterExpression, ParameterExpression> ParameterReplacements
{
get;
set;
}
protected override Expression VisitParameter(ParameterExpression node)
{
ParameterExpression replacement;
if (ParameterReplacements.TryGetValue(node, out replacement))
node = replacement;
return base.VisitParameter(node);
}
}
class Program
{
static void Main(string[] args)
{
Expression<Func<int, bool>> exprA = a => a == 3;
Expression<Func<int, bool>> exprB = b => b == 4;
Expression<Func<int, bool>> exprC =
Expression.Lambda<Func<int, bool>>(
Expression.OrElse(
exprA.Body,
new ExpressionParameterReplacer(exprB.Parameters, exprA.Parameters).Visit(exprB.Body)),
exprA.Parameters);
Console.WriteLine(exprA.ToString());
Console.WriteLine(exprB.ToString());
Console.WriteLine(exprC.ToString());
Func<int, bool> funcA = exprA.Compile();
Func<int, bool> funcB = exprB.Compile();
Func<int, bool> funcC = exprC.Compile();
Debug.Assert(funcA(3) && !funcA(4) && !funcA(5));
Debug.Assert(!funcB(3) && funcB(4) && !funcB(5));
Debug.Assert(funcC(3) && funcC(4) && !funcC(5));
}
}
}