在填充现有对象时添加项目之前清除集合 [英] Clear collections before adding items when populating existing objects

查看:28
本文介绍了在填充现有对象时添加项目之前清除集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象,它有几个用公共 getter 但私有 setter 定义的集合属性,在这种情况下,JsonConvert.PopulateObject 将反序列化的项目添加到这些集合中,而现有项目保持不变.

I have an object which has several collection properties defined with public getter but private setter, In this case JsonConvert.PopulateObject adds the deserialized items to these collections leaving the existing items untouched.

当此类成员集合在反序列化之前被清除时,我需要一种行为.

I need a behavior when such member collections get cleared before deserialization.

我尝试在标有 [OnDeserializing] 属性的方法中手动清除集合.

I tried to manually clear the collections in a method marked with the [OnDeserializing] attribute.

这种方法的问题在于,即使 JSON 字符串中不存在集合属性,它仍然会清除集合.

The problem with that approach is that it will still clear the collections even if the collection property does not exist in the JSON string.

当只有那些在 JSON 字符串中实际定义的集合被清除时,我需要一种方法.那些未定义的应该保持不变.

I need a way when only those collections get cleared which are actually defined in the JSON string. Those which are undefined should be kept untouched.

谢谢

推荐答案

好的,经过一番访问 Json.NET 资源后,我通过从 DefaultContractResolver 继承自定义合约解析器找到了以下解决方案.

Okay, so after some trip to Json.NET sources I found the following solution by inheriting a custom contract resolver from DefaultContractResolver.

我需要重写数组合约创建以添加反序列化回调.此时回调接收到具体的集合实例,因此我们可以对其进行操作(在这种情况下清除它).

I needed to override the array contract creation to add a deserialization callback. At this point the callback receives the concrete collection instance, so we can manipulate it (in this case clear it).

只要我能确定,使用它是安全的,但请随时警告这种方法的任何缺点.

As long as I can determine, it is safe to use, but feel free to warn about any drawbacks of this method.

注意:我是唯一认为这应该是默认行为的人吗?

public class CollectionClearingContractResolver : DefaultContractResolver
{
    protected override JsonArrayContract CreateArrayContract(Type objectType)
    {
        var c = base.CreateArrayContract(objectType);
        c.OnDeserializingCallbacks.Add((obj, streamingContext) =>
        {
            var list = obj as IList;
            if (list != null && !list.IsReadOnly)
                list.Clear();
        });
        return c;
    }
}

...

public class Test {
    public List<int> List { get; private set; }
    public Test() {
        List = new List<int>();
    }
}  

...

var myObj = new Test();
myObj.List.AddRange(new[] {1,2,3});
var listReference = myObj.List;    

JsonConvert.PopulateObject("{ List: [4, 5, 6] }", myObj, 
    new JsonSerializerSettings {
        ContractResolver = new CollectionClearingContractResolver(),
    });

myObj.List.ShouldEqual(listReference); // didn't recreate list
myObj.List.Count.ShouldEqual(3);
myObj.List.SequenceEqual(new[] { 4, 5, 6}).ShouldBeTrue();

这篇关于在填充现有对象时添加项目之前清除集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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