问题设置
我尝试使用System.Linq.Dynamic.Core包在我的应用中实现验证规则,但是遇到了奇怪的行为。我的想法是能够在应用本身中创建和管理这些验证规则。因此,我在数据库中定义了一个ValidationRule
对象:
public class ValidationRule {
public string Description { get; set; }
public string ErrorMessage { get; set; }
public short Id { get; set; }
public bool IsActive { get; set; }
public string Name { get; set; }
public string NewExpression { get; set; }
public string OldExpression { get; set; }
}
NewExpression
和OldExpression
属性包含要传递给Any()
动态版本的表达式。ValidationRule
对象的重要部分只有Name
、ErrorMessage
、NewExpression
和OldExpression
,因此我将它们投影到DTO中:
public class ValidationRuleDto {
public string ErrorMessage { get; set; }
public string Name { get; set; }
public string NewExpression { get; set; }
public string OldExpression { get; set; }
}
然后将此DTO传递给ValidationRuleHandler
,以使用来自DTO的表达式对正在验证的对象的旧示例和新示例进行求值。ValidationRuleHandler
如下所示:
public static class ValidationRuleHandler {
private static readonly ParsingConfig _parsingConfig = new() {
AreContextKeywordsEnabled = false
};
public static ICollection<string> Validate(
dynamic oldObject,
dynamic newObject,
IEnumerable<ValidationRuleDto> rules) => rules.Select(
_ => {
var oldResult = new[] {
oldObject
}.AsQueryable().Any(_parsingConfig, _.OldExpression);
var newResult = new[] {
newObject
}.AsQueryable().Any(_parsingConfig, _.NewExpression);
Debug.WriteLine($"Old => {oldObject.StageText} => {_.OldExpression} => {oldResult}");
Debug.WriteLine($"New => {newObject.StageText} => {_.NewExpression} => {newResult}");
return !(oldResult && newResult)
? null
: $"[{_.Name}] {_.ErrorMessage}";
}).Where(
_ => _ != null).ToHashSet();
}
对于传递给Validate()
的新旧对象,我将对象投影到旧快照中(从数据库原样)和新快照在Validate()
中,我将每个对象添加到单个项集合中,并将它们转换为IQueryable
,以便可以使用动态Any()
。我在这里的思路是,规则的表达式只需要计算出true/false结果,并且由于如果表达式的条件通过,Any()
将返回true/false,因此这似乎是最合适的方法。
问题
我遇到的问题是,在运行应用程序时,我所期望的结果并没有出现。(5.2.9)应用程序。但是,使用LINQPad时(5.46.00)来测试ValidationRuleHandler
,结果是正确的。例如,以下是应用程序中Debug
语句的输出:s处理应用于用户的三个验证规则:
- 旧=〉未售出=〉(阶段文本!=“已关闭”)=〉True
- 新建=〉已关闭=〉(阶段文本==“已关闭”)=〉错误错误
- 旧版=〉未售出=〉(StageText!=“未售出”)=〉正确错误
- 新建=〉已关闭=〉(阶段文本==“未售出”)和(未售出原因文本==空)=〉假
- 旧=〉未售出=〉(StageText!=“准备开票”)=〉True
- 新建=〉已关闭=〉(阶段文本==“准备开票”)和(定价方法文本==空)=〉假
以下是完全相同的验证规则和快照对象(完全相同的值)的LINQPad结果:
- 旧=〉未售出=〉(阶段文本!=“已关闭”)=〉True
- 新建=〉已关闭=〉(阶段文本==“已关闭”)=〉True
- 旧=〉未售出=〉(阶段文本!=“未售出”)=〉假
- 新建=〉已关闭=〉(阶段文本==“未售出”)和(未售出原因文本==空)=〉假
- 旧=〉未售出=〉(StageText!=“准备开票”)=〉True
- 新建=〉已关闭=〉(阶段文本==“准备开票”)和(定价方法文本==空)=〉False
正如您所看到的,当从LINQPad调用ValidationRuleHandler
时,它正确地计算表达式,但当从应用程序处理时,它是错误的。
我不明白为什么它会这样。仔细想想,我看不出有什么问题,LINQPad的表现和预期的一样,但应用程序却不是,我不知道还能做什么。如果有人有任何建议,我将不胜感激。如果有人以前不得不处理类似的事情,我也愿意接受替代建议,以实现同样的目标。
2条答案
按热度按时间mftmpeh81#
创建.NET Full Framework 4.8控制台应用程序时,使用以下示例代码:
看起来效果不错:
7lrncoxx2#
因此,在尝试了许多个小时的不同解决方案来查看它到底在哪里失败之后,没有任何效果,直到我将表达式改为使用
Equals()
。之后立即工作了,我不知道为什么会这样:(StageText.Equals("Closed"))
;的工作原理和以下内容:(StageText == "Closed")
;不会。我仍然很困惑,为什么我在LINQPad中测试时,原来的方法可以工作,而在应用程序中却不行。@Stef也证实了它的工作,所以我很困惑。也许它与从数据库中提取快照值有关,或者也与从数据库中提取验证规则表达式有关?
无论如何,它与
Equals()
一起工作,所以我正在使用它。