1

わかりました、これで基本的なクラスのセットアップができました...

public class Location
{
    public string Name{ get; set; }

    private LocationList _LocationList = new LocationList();   
    public LocationList Locations{ get{ return _LocationList; } }
}

public class LocationList : List<Location>{}

public class ViewModel
{
    private LocationList _LocationList = new LocationList();   
    public LocationList Locations{ get{ return _LocationList; } }
}

これを Newtonsoft JSON シリアライザーで使用したいと考えています。ただし、シリアライザーは、読み取り専用プロパティ アクセサーの背後にある既存のコレクションにアイテムを挿入するのではなく、まったく新しい List をプロパティに割り当てようとします。もちろん、セッターがないため、これはできません。

これで切り替えられるようになりました...

public class Location
{
    public string Name{ get; set; }
    public LocationList Locations{ get; set; }
}

public class LocationList : List<Location>{}

public class ViewModel
{
    public LocationList RootLocations{ get; set; }
}

しかし、現在、list プロパティは読み取り専用ではなく、null に設定できます。セッターを非公開にしても、JSON デシリアライズで null に設定できます。

私が欲しいのは、「リストを完全にあなたのものに置き換える」と言うのではなく、シリアライザーに「リストにあるアイテムを取得して、この既存のリストに挿入する」ように伝える方法です。

これを行うことはできますか、それとも独自の JSON シリアライゼーション コンバーターを作成してプラグインする必要がありますか?

M

4

1 に答える 1

0

JSON.NETについてはわかりませんが、使用するJavaScriptSerializer場合はカスタムシリアライザーを提供できますが、組み込みの解析/フォーマットなどを使用できます:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Web.Script.Serialization;


class Program
{
    static void Main(string[] args)
    {

        JavaScriptSerializer ser = new JavaScriptSerializer();
        ser.RegisterConverters(new[] { new ViewModelConverter() });

        var model = new ViewModel { Locations = { new Location { Name = "abc",
            Locations = { new Location { Name = "def"}}} } };
        var json = ser.Serialize(model);

        var clone = (ViewModel)ser.Deserialize(json, typeof(ViewModel));
    }

}

public class ViewModelConverter : JavaScriptConverter
{

    public override IEnumerable<Type> SupportedTypes
    {
        get { return new[] { typeof(Location), typeof(ViewModel) }; }
    }
    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        if (obj is ViewModel)
        {
            return new Dictionary<string, object> { { "locations", ((ViewModel)obj).Locations } };
        }
        if (obj is Location)
        {
            return new Dictionary<string, object> {
                {"name", ((Location)obj).Name},
                { "locations", ((Location)obj).Locations }
            };
        }
        throw new NotSupportedException();
    }
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        if (type == typeof(ViewModel))
        {
            var model = new ViewModel();
            ReadLocations(model.Locations, dictionary, serializer);
            return model;
        }
        if (type == typeof(Location))
        {
            var loc = new Location();
            if (dictionary.ContainsKey("name"))
            {
                loc.Name = (string)dictionary["name"];
            }
            ReadLocations(loc.Locations, dictionary, serializer);
            return loc;
        }
        throw new NotSupportedException();
    }
    static void ReadLocations(LocationList locations, IDictionary<string, object> dictionary, JavaScriptSerializer serializer)
    {
        if (dictionary.ContainsKey("locations"))
        {
            foreach (object item in (IList)dictionary["locations"])
            {
                locations.Add((Location)serializer.ConvertToType<Location>(item));
            }
        }
    }
}
public class Location
{
    public string Name { get; set; }

    private LocationList _LocationList = new LocationList();
    public LocationList Locations { get { return _LocationList; } }
}

public class LocationList : List<Location> { }

public class ViewModel
{
    private LocationList _LocationList = new LocationList();
    public LocationList Locations { get { return _LocationList; } }
}
于 2011-05-03T05:31:52.330 に答える