我的delegate
如下:
public delegate TestResult TestCase(byte[] source);
...返回TestResult
如下:
public class TestResult {
public bool Pass { get; }
public int Index { get; }
public TestResult(bool result, int index) {
Pass = result;
Index = index;
}
}
一个示例TestCase
委托看起来像:
public static TestResult In(byte[] tkn, ITestSet testSet) {
return testSet.Contains(tkn);
}
ITestSet
不只是封装的HashSet<byte[]>
。
在一个用例中,我有2个测试集:(1)A -z,(2)0-9。我想测试输入byte[]
是否在任何一个测试集中。
我正在使用Expression<TestCase>
,但是很难弄清楚如何实现Or
测试用例。我有一个具有以下方法的TestCaseBuilder
:
public class TestCaseBuilder {
private Expression<TestCase> tcExpr;
public TestCaseBuilder With(TestCaseBuilder tcBuilder) {
tcExpr = tcBuilder.tcExpr;
return this;
}
public TestCaseBuilder Or(TestCaseBuilder tcBuilder) {
tcExpr = tcExpr.Or(tcBuilder.tcExpr);
return this;
}
}
...和我的扩展方法:
public static Expression<TestCase> Or (this Expression<TestCase> tcLeft, Expression<TestCase> tcRight) {
var lExpr = (LambdaExpression)tcLeft;
var rExpr = (LambdaExpression)tcRight;
var param = lExpr.Parameters;
return Expression.Lambda<TestCase>(/* what to do here ? */, param);
}
Expression.OrElse
在机械上是我认为适当的,但由于我返回TestResult
而不是bool
。
这是使用TestCaseBuilder
的方式:
testcaseBuilder.As("Foo")
.With(isLetterTestCase)
.Or(isDigitTestCase);
我仅使用TestCase
代表进行了Or
:
public static TestCase Or(this TestCase tc1, TestCase tc2) {
return tkn => {
var res = tc1(tkn);
if (res.Pass) {
return res;
}
return tc2(tkn);
};
}
如何在自定义Or
方法中组合2个Expression<TestCase>
,而无需调用第一个测试案例?
这是您想要的
public static Expression<Func<byte[], TestResult, TestCase, TestResult>> helperExp = (inp, res, next) => res.Pass ? next(inp) : res;
public static Expression<TestCase> Or(Expression<TestCase> exp1, Expression<TestCase> exp2)
{
var param = exp1.Parameters;
Expression<TestCase> or = Expression.Lambda<TestCase>(
Expression.Invoke(helperExp,
param[0], Expression.Invoke(exp1, param), exp2),param);
return or;
}
带有块表达式无调用
public static Expression<TestCase> Or(Expression<TestCase> exp1, Expression<TestCase> exp2)
{
var param = exp1.Parameters;
ParameterExpression local = Expression.Parameter(typeof(TestResult), "local");
BlockExpression block = Expression.Block(
new[] { local },
Expression.Assign(local, exp1.Body),
Expression.Condition(Expression.Property(local, nameof(TestResult.Pass)), exp2.Body, local));
return Expression.Lambda<TestCase>(block, param);
}
测试
Expression<TestCase> exp1 = (tc) => new TestResult(true);
Expression<TestCase> exp2 = (tc) => new TestResult(false);
var first = Or(exp1, exp1);
var second = Or(first, exp2);
var func = second.Compile();
var result = func(new byte[] { });
使用https://github.com/louthy/csharp-monad,可能有更好的方法来进行有条件的单元,而无需表达我的东西.NET Core将中间件的单调原理使用。