避免默认构造和公共财产setter方法 [英] Avoiding default constructors and public property setters

查看:128
本文介绍了避免默认构造和公共财产setter方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的工作与SignalR一个项目,我有一些对象我会沿着穿过它。这些对象在我的后端代码只明确创建的,我真的很想能够强制执行不变性和不变量他们。我遇到的问题是SignalR需要我(当然,真正NewtonSoft.Json),有一个默认的,无参数的构造函数和公共setter方法​​对我的性质以便它序列化和反序列化它们通过线路。

I'm working on a project with SignalR, and I've got some objects that I'm going to be passing along through it. These objects are only explicitly created in my back-end code, and I'd really like to be able to enforce immutability and invariants on them. I'm running into the issue that SignalR requires me (well, really NewtonSoft.Json), to have a default, no-args constructor and public setters on my properties in order for it to serialize and deserialize them over the wire.

下面是一个人为的例子:

Here's a contrived example:

public class Message{
    public string Text {get;set;}
    public int Awesomeness {get;set;}
}

我想要什么,是沿着这些路线的更多的东西(它可能应该有只读私有字段,只吸气的属性是完全不变的,但对于一些仅仅是一个POCO,没有方法,不够好)

What I'd like, is something more along these lines (it should probably have readonly private fields and getter-only properties to be fully immutable, but for something that is just a POCO with no methods, good enough)

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客户端库得到反序列化。我可以扔掉默认构造函数在那里,让我制定者众,但我一定要记得在我的代码不使用它们,并确保没有其他人对球队使用它们不理解。

If I do that, though, my object can't get deserialized by the SignalR .NET client library. I can just chuck a default constructor in there, and make my setters public, but then I have to remember to not use them in my code, and make sure no one else on the team uses them without understanding.

我身边这样的想法踢,以纪念默认构造函数的东西,不应该被明确使用:

I've kicked around the idea of doing this, to mark the default constructor as something that should never be explicitly used:

[Obsolete("Bad! don't do this!")
public Message(){}

但我不能使用过时的属性上的属性只是二传手。

But I can't use the Obsolete attribute on just the setter of a property.

如果我真的想,我可以从DTO表示分离出真正的对象,它们之间的转换,但我不是真的吓坏了写一堆样板做到这一点,引进另一层。

If I really wanted to, I could separate out the "real" object from a DTO representation and convert between them, but I'm not really psyched up to write a bunch of boilerplate to do that and introduce another layer.

有我忽视的东西,或者我只需要硬着头皮处理呢?

Is there something I'm overlooking, or do I just need to bite the bullet and deal with it?

推荐答案

如果你的类没有公共参数的构造函数,但确实有一个带参数的单一的公共构造函数,Json.NET将调用构造函数,的使用反射的名字相匹配的构造函数参数的JSON属性的和使用缺少的属性的默认值。与之相匹配的名称是区分大小写的,除非有只有大小写不同,在这种情况下,比赛变得区分大小写多个匹配。因此,如果你简单地做:

If your class does not have a public parameterless constructor, but does have a single public constructor with parameters, Json.NET will call that constructor, matching the constructor arguments to the JSON properties by name using reflection and using default values for missing properties. Matching by name is case-insensitive, unless there are multiple matches that differ only in case, in which case the match becomes case sensitive. Thus if you simply do:

public class Message
{
    public string Text { get; private set; }
    public int Awesomeness { get; private set; }
    public Message(string text, int awesomeness)
    {
        if (awesomeness < 1 || awesomeness > 5)
        {
            throw new ArgumentOutOfRangeException("awesome");
        }
        this.Text = text;
        this.Awesomeness = awesomeness;
    }
}

您将能够序列化,并成功反序列化类与Json.NET。

You will be able to serialize and deserialize your class successfully with Json.NET.

小提琴。

如果你的类有多个公共构造,所有的参数,你可以标记一个与的 [JsonConstructor] ,例如:

If your class has multiple public constructors, all with parameters, you can mark the one to use with [JsonConstructor], e.g.:

public class Message
{
    public string Text { get; private set; }
    public int Awesomeness { get; private set; }

    public Message(string Text)
        : this(Text, 1)
    {
    }

    [JsonConstructor]
    public Message(string text, int awesomeness)
    {
        if (awesomeness < 1 || awesomeness > 5)
        {
            throw new ArgumentOutOfRangeException("awesome");
        }
        this.Text = text;
        this.Awesomeness = awesomeness;
    }
}



又见的 JsonSerializerSettings.ConstructorHandling 告诉Json.NET是否喜欢一个非公开的参数构造函数与多参数的单个公共构造函数。

See also JsonSerializerSettings.ConstructorHandling which tells Json.NET whether to prefer a non-public parameterless constructor over a single public constructor with parameters.

这篇关于避免默认构造和公共财产setter方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆