【发布时间】:2016-02-06 19:11:18
【问题描述】:
我正在使用 SignalR 开展一个项目,并且我有一些我将通过它传递的对象。这些对象仅在我的后端代码中显式创建,我真的希望能够对它们强制执行不变性和不变量。我遇到了 SignalR 需要我(嗯,真的是 NewtonSoft.Json)在我的属性上有一个默认的、无参数的构造函数和公共设置器的问题,以便它通过网络对它们进行序列化和反序列化。
这是一个人为的例子:
public class Message{
public string Text {get;set;}
public int Awesomeness {get;set;}
}
我想要的是更多类似这些方面的东西(它可能应该具有只读私有字段和仅 getter 属性以完全不可变,但对于只是一个没有方法的 POCO 来说,已经足够好了)
public class Message {
public string Text {get;private set;}
public int Awesomeness {get;private set;}
public Message( string msg, int awesome){
if (awesome < 1 || awesome > 5){
throw new ArgumentOutOfRangeException("awesome");
}
Text = msg;
Awesomeness = awesome;
}
}
但是,如果我这样做,我的对象将无法被 SignalR .NET 客户端库反序列化。我可以在其中放置一个默认构造函数,并将我的设置器公开,但是我必须记住不要在我的代码中使用它们,并确保团队中的其他人在不理解的情况下使用它们。
我已经提出了这样做的想法,将默认构造函数标记为永远不应该显式使用的东西:
[Obsolete("Bad! don't do this!")
public Message(){}
但我不能只在属性的 setter 上使用 Obsolete 属性。
如果我真的想这样做,我可以将“真实”对象从 DTO 表示中分离出来并在它们之间进行转换,但我并不想写一堆样板来做到这一点并引入另一层。
有什么我忽略了,还是我只需要硬着头皮处理它?
【问题讨论】:
-
不确定这是否可行,但如果您将参数设置为可选,反序列化器是否工作?
-
您是否尝试过使用
[JsonProperty]和[JsonConstructor]属性?您可以将它们放在私人成员上,以让 Json.Net “看到”它们。您还可以为您的对象创建 JsonConverters。见JSON.net: how to deserialize without using the default constructor?。 -
您确定 setters 需要公开吗?我以为只要有私人二传手在场,你就可以逍遥法外?