Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# JSON.NET如何设置get only IEnumerable<;T>;财产?_C#_Json.net - Fatal编程技术网

C# JSON.NET如何设置get only IEnumerable<;T>;财产?

C# JSON.NET如何设置get only IEnumerable<;T>;财产?,c#,json.net,C#,Json.net,在下面的示例中,foo和反序列化dfoo变量都有一个完全填充的Values属性。私有的无操作构造函数被赋予[json构造函数]属性,以避免从公共构造函数映射构造函数值 尽管如此,如果JSON.NET的支持字段在构造期间分配给空列表,那么它似乎能够设置get only属性的值 我在JSON.NET文档中找不到任何关于这种行为的提及。有人能解释这种行为吗 void Main() { var foo=新foo(新[]{“一”、“二”、“三”}); var json=JsonConvert.Serial

在下面的示例中,
foo
反序列化dfoo
变量都有一个完全填充的
Values
属性。私有的无操作构造函数被赋予
[json构造函数]
属性,以避免从公共构造函数映射构造函数值

尽管如此,如果JSON.NET的支持字段在构造期间分配给空列表,那么它似乎能够设置get only属性的值

我在JSON.NET文档中找不到任何关于这种行为的提及。有人能解释这种行为吗

void Main()
{
var foo=新foo(新[]{“一”、“二”、“三”});
var json=JsonConvert.SerializeObject(foo);
var deserializedFoo=JsonConvert.DeserializeObject(json);
}
福班
{
私有只读列表_值;
公共Foo(IEnumerable值)
{
_values=values.ToList();
}
[JsonConstructor]
私家富()
{
_值=新列表();
}
公共IEnumerable值=>\u值;
}

我不确定这是在哪里记录的(如果有),但在对象反序列化期间,如果已经分配了引用类型成员,Json.NET将重新使用现有成员实例,而不是分配新的成员实例。然后,它将使用成员值的实际、具体的类型(而不是声明的类型)将JSON填充到成员中。在您的例子中,
Values
返回的对象的实际具体类型是
List
——Json.NET能够填充它

如果我更改
以实际返回只读枚举,如下所示:

public IEnumerable<string> Values => _values.AsReadOnly();
它是有人居住的。演示小提琴2

作为最后一个演示,如果我修改您的
Foo
模型,使其具有一些额外的预分配只读属性
Bar
,该属性仅声明为
对象
,如下所示:

public object Values => _values;
class Foo
{
    private readonly List<string> _values;
    private readonly Bar _bar = new Bar();

    public Foo(IEnumerable<string> values)
    {
        _values = values.ToList();
    }

    [JsonConstructor]
    private Foo()
    {
        _values = new List<string>();
    }

    public IEnumerable<string> Values { get { return _values; } }

    public object Bar { get { return _bar; } }
}

public class Bar
{
    public string Property1 { get; set; }
}
class-Foo
{
私有只读列表_值;
专用只读条_Bar=new Bar();
公共Foo(IEnumerable值)
{
_values=values.ToList();
}
[JsonConstructor]
私家富()
{
_值=新列表();
}
公共IEnumerable值{get{return\u Values;}}
公共对象栏{get{return}
}
公共类酒吧
{
公共字符串属性1{get;set;}
}
然后,将成功填充属性引用的实际对象:

var json = @"{""Values"":[""One"",""Two"",""Three""],""Bar"":{""Property1"":""Test""}}";
var deserializedFoo = JsonConvert.DeserializeObject<Foo>(json);
Assert.IsTrue(deserializedFoo.Values.Count() == 3 && ((Bar)deserializedFoo.Bar).Property1 == "Test"); // No Assert
var json=@“{”值“:[“一”、“二”、“三”],“条”:“{”属性1“:“测试”}”;
var deserializedFoo=JsonConvert.DeserializeObject(json);
Assert.IsTrue(deserializedFoo.Values.Count()==3&((Bar)deserializedFoo.Bar).Property1==“Test”);//无断言
演示小提琴#3

如果你不想要这种行为,你有什么选择

首先,可以将集合包装在只读包装器中,如上所示。一般来说,这不是一个坏主意,因为它可以防止
Foo
类型的消费者简单地将
值转换为
列表并对其进行修改

其次,可以使用
ObjectCreationHandling.Replace进行反序列化。启用此设置后,Json.NET将始终为预分配的读/写属性分配新值,并跳过预分配的只读属性。小提琴示范曲#4。注意,这可以防止引用任何.Net引用类型的只读成员的填充,而不仅仅是集合


第三,您可以采用从到的方法,并创建一个自定义契约解析器,该解析器将不应反序列化的属性设置为返回false的谓词。

我猜这是通过反射魔法完成的……我想您可以在,虽然我不太清楚如何/在哪里:)你认为这里会发生什么?非常全面的答案。非常感谢。