亲爱的社区:D
现在我正在开展我的第一个大项目并且有点卡住了。 我正在尝试验证一些输入。
因此我正在使用此功能:
public static Validatable<string> RequiredOr(this Validatable<string> that, Func<Validatable<string>, bool> func)
{
return that.DoEvaluate && !(func(that) || that.Value != null)
? that.Error(ML.Get("Validation", "IsRequired"))
: that;
}
对于正常验证我正在使用:
public Validatable<TProperty> Validate<TProperty>(
Expression<Func<TEntity, TProperty>> expr)
{
return new Validatable<TProperty>(
new ErrorTrackerWrapper(ErrorTracker, expr.Body), expr.Compile()(Value));
}
这部分称为“RequiredOr”功能:
var header = from name in v.Validate(it => it.Name).Required().MaxLength(Constants.String.NameLength)
from startDate in v.Validate(it => it.StartDate).Required().After(DateTime.Today)
from endDate in v.Validate(it => it.EndDate).Required().After(DateTime.Today)
from endTime in v.Validate(it => it.EndTime).BlockErrors().Required().ReplaceIfInvalid(new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 30, 0))
from requestedCurrency in v.Validate(it => it.RequestedCurrency).Required()
from language1 in v.Validate(it => it.Language1).Required()
from language2 in v.Validate(it => it.Language2)
from language3 in v.Validate(it => it.Language3)
from hasMoreInformation in v.Validate(it => it.HasMoreInformation)
// TODOJP: If "hasMoreInformation" is true, then "moreInformationEmail" has to be required.
from moreInformationEmail in v.Validate(it => it.MoreInformationEmail).IsEmail()//.RequiredOr(p => !hasMoreInformation)
from isAnonymous in v.Validate(it => it.IsAnonymous)
select new AnnouncementHeader(
currentUser,
type,
name,
startDate,
endDate.SetTime(new Time(endTime.Hour, endTime.Minute)),
isAnonymous,
infoField,
requestedCurrency,
language1,
language2,
language3,
hasMoreInformation,
moreInformationEmail);
到目前为止,这是正确的,但有些如何,它一直告诉我“RequiredOr”部分中的“hasMoreInformation”是一个NullReferenceException。
我能够将错误追溯到“RequiredOr”函数。
我想检查“HasMoreInformation”是否为真,然后将字段设置为“必需”。
我希望你的家伙明白我要告诉你的是什么。 非常感谢你的帮助。
答案 0 :(得分:0)
对于可能为空的对象,您必须在测试该字段是否为真之前测试该字段是否存在。违反规则的后果是空引用异常。这就是它的工作原理。
如果该项可以为空,则始终存在空值。如果你默认值,你可以不这样做,但是默认值必须具有单一含义,并不意味着“它可以是默认值”和“它可以由用户显式设置”。
如果默认值没有意义,那么在验证之前,您假设一个空对象表示有效或无效。
由于我的上下文很少,我建议以长篇形式写出来解决问题。然后,您可以重新考虑延迟执行样式(LINQ)。我之所以这么说,是因为你似乎只想选择有效的,当项目不为空时以及其他没有明确说明的内容(基于关于之后需要检查的评论)。 LINQ它之前解决问题。
新:在LINQ-up解决方案之前仍然坚持最后一行解决方案(我将在这里包括所有形式的延迟执行,而不仅仅是LINQ)。
如果没有我在语句上花费大量时间,你有一些LINQ和一些扩展方法(带有链接方法的流畅语法,等等,等等)。所有这些都是延迟执行。如果您要下拉符号并弹出堆栈,您可能会发现延迟执行的顺序是问题的一部分。它通常是调试抽象堆的唯一方法。 (是的,我已经看到了一个带有函数指针和扩展方法的47行嵌套LINQ语句)
当你使用流体编程风格时,你实际上是在运行伪IoC类型的模式,因为最右边的方法会转到下一个方法,直到你一直向左移动。非常糟糕的类比解释,所以我可能会得到纠正,但是你正在使用函数指针来保持流程的正确方法。例如:
Colonel.Sanders.Loves.Chicken( “炒”);
函数指针,扩展方法和RX,哦,我的!从哲学的角度来看相当简洁的东西,但如果你真的不明白它是如何工作的,那就容易出现糟糕的juju。它通常会产生非常清晰的语法,但会产生调试噩梦。
如果你进一步坚持在LINQ声明中选择膳食计划或快餐店,你会得到很多来自不同方向的延迟声明。并且,如果一个位的顺序不正确,则某些代码会在必要的前导之前运行。由于LINQ和扩展方法使用不同的方法,因此将它们混合会增加以不正确的顺序运行位的可能性。使用符号进行调试通常是唯一的方法,因为整个延迟抽象的blob在运行时被“编译”。
所以,要结束这篇长篇文章,你需要a)调试并弄清楚为什么你得到空引用(很可能是你的延迟执行堆栈中的调用错误)或b)首先解决问题使用非延迟方法(或者一次运行一个延迟的goo?)。