【发布时间】:2020-12-07 15:38:13
【问题描述】:
假设我有一个使用 C# 可为空引用对象功能的配置或 DTO 对象:
public class ServiceConfig
{
public string ConnectionString { get; set; }
public string? OptionalComment { get; set; }
}
使用上面的代码,我收到编译器警告“CS8618:退出构造函数时不可为空的属性 'ConnectionString' 必须包含非空值。考虑将属性声明为可空。”因为这个对象 需要 无参数构造函数,我可以添加 = null! 来消除警告。但问题是对象仍然可以包含具有空值的属性。因为我想在配置和 DTO 的上下文中使用它,所以可以选择在将对象传递给“真实”对象之前验证对象(在反序列化过程中)。
我该怎么做?有一种方法可以通过“可空引用”表示法验证对象是否有效?我看到其他选项也与数据注释有关,但我使用这个 C# 功能更有吸引力。
所以,在幻想中我想要这样的东西:
public class ServiceConfig
{
public string ConnectionString { get; set; } = null!;
public string? OptionalComment { get; set; }
}
public class Deserializer
{
public static ServiceConfig Deserialize(string data)
{
var result = Json.Deserialize<ServiceConfig>(data);
var isObjectValid = result.IsValid(); // I want method something like this
if (!isObjectValid) throw new Exception("Deserialization error");
return result;
}
}
【问题讨论】:
-
这能回答你的问题吗? How to use .NET reflection to check for nullable reference type。基本上,您将检查每个属性是否可以为空,如果不是,则检查它是否包含
null。 NRT 注释的存储方式并非微不足道,因此该检查也不是微不足道的。注释可以实现更多的验证,而不仅仅是可空性。 -
如果你可以使用 Json.Net 应该可以使用非空构造函数:stackoverflow.com/questions/23017716/…
-
我的建议是检查是否可以使用源生成器 (devblogs.microsoft.com/dotnet/introducing-c-source-generators),这将为您提供 IsValid() 方法
-
您是否考虑过添加一个无参数构造函数,将值设置为 "" 而不是 null?
-
这里的根本问题是你有一个单一的类型试图代表两种不同的状态——一个未验证的对象(ConnectionString 可以为空)和一个验证的对象(不能)。如果您想对事物真正严格,您可能希望将这些概念分成两种类型 - 一种仅用于反序列化目的,然后让您的 Validate 方法实际验证 并将 转换为更严格的类型。这确实意味着很多重复,但根据我的经验,它可以带来各种好处。
标签: c# nullable-reference-types