2

コレクションが型として表されるオブジェクトモデルにjsonを逆シリアル化しようとしていIList<T>ます。

実際の逆シリアル化はここにあります:

JavaScriptSerializer serializer = new JavaScriptSerializer();

return serializer.Deserialize<IList<Contact>>(
    (new StreamReader(General.GetEmbeddedFile("Contacts.json")).ReadToEnd()));

例外を投稿する前に、暗黙の変換が何であるかを知っておく必要があります。これはContactタイプです:

public class Contact
{
    public int ID { get; set; }
    public string Name { get; set; }
    public LazyList<ContactDetail> Details { get; set; }
    //public List<ContactDetail> Details { get; set; }
}

そしてこれはContactDetailタイプです:

public class ContactDetail
{
    public int ID { get; set; }
    public int OrderIndex { get; set; }
    public string Name { get; set; }
    public string Value { get; set; }
}

で知っておくべき重要なことLazyList<T>は、それが実装しているということIList<T>です:

public class LazyList<T> : IList<T>
{
    private IQueryable<T> _query = null;
    private IList<T> _inner = null;
    private int? _iqueryableCountCache = null;


    public LazyList()
    {
        this._inner = new List<T>();
    }

    public LazyList(IList<T> inner)
    {
        this._inner = inner;
    }

    public LazyList(IQueryable<T> query)
    {
        if (query == null)
            throw new ArgumentNullException();
        this._query = query;
    }

LazyList<T>これで、 Jsonを逆シリアル化しようとするまで、このクラス定義は問題ありませんでした。は、その年齢の意味のあるSystem.Web.Script.Serialization.JavaScriptSerializerリストをシリアル化したいと思っているようですが、それらが私の中にキャストされるように、タイプでそれらが必要です(少なくともそれは私が間違っていると思うところです)。List<T>IList<T>LazyList<T>

この例外が発生します:

System.ArgumentException: Object of type 'System.Collections.Generic.List`1[ContactDetail]' cannot be converted to type 'LazyList`1[ContactDetail]'..

List<ContactDetail>私が私のタイプで使用しようとするContactと(上記のコメントを見ることができるように)、それはうまくいくようです。しかし、私はを使いたくありませんList<T>LazyList<T>実行しているように見える継承を試してみましたが、内部を実装にList<T>渡すのは悪夢であり、モデルのどこにも肥大化したくないだけです。List<T>T[]List<T>

また、他のいくつかのjsonライブラリを無駄に試しました(これらを最大限に活用していない可能性があります。多かれ少なかれ参照を置き換えて、この質問の上部に引用されているコードを繰り返してみました。おそらく、settingsparamsを渡すとヘルプ??)。

今何をしようかわからない。別のデシリアライザーを使用しますか?デシリアライズ自体を微調整しますか?デシリアライザーを満足させるためにタイプを変更する必要がありますか?暗黙のキャストについてもっと心配する必要がありますか、それとも単に別のインターフェイスを実装する必要がありますか?

4

3 に答える 3

0

インターフェイスは単なるコントラクトであるため、インターフェイスに直接デシリアライズすることはできません。JavaScriptSerializerは、IList <T>を実装する具体的なタイプに逆シリアル化する必要があり、最も論理的な選択はList<T>です。リストをLazyListに変換する必要があります。これにより、投稿したコードが十分に簡単になります。

var list = serializer.Deserialize<IList<Contact>>(...);
var lazyList = new LazyList(list);
于 2009-10-18T05:27:39.110 に答える
0

ListはIListの実装であるため、デシリアライザーがIList型である必要があることを知る方法がないため、残念ながらクラスを修正する必要があります。

http://json.orgのデシリアライザーには利用可能なソースがあるため、必要に応じて1つを変更するだけで済みます。

于 2009-10-18T05:31:09.960 に答える
0

最終的に、カスタムマッピングを適切にサポートするJson.NETlibを使用しました。これは私の逆シリアル化がどのようになってしまったかです:

        JArray json = JArray.Parse(
            (new StreamReader(General.GetEmbeddedFile("Contacts.json")).ReadToEnd()));

        IList<Contact> tempContacts = (from c in json
                                       select new Contact
                                       {
                                           ID = (int)c["ID"],
                                           Name = (string)c["Name"],
                                           Details = new LazyList<ContactDetail>(
                                               (
                                                   from cd in c["Details"]
                                                   select new ContactDetail
                                                   {
                                                       ID = (int)cd["ID"],
                                                       OrderIndex = (int)cd["OrderIndex"],
                                                       Name = (string)cd["Name"],
                                                       Value = (string)cd["Value"]
                                                   }
                                                ).AsQueryable()),
                                           Updated = (DateTime)c["Updated"]
                                       }).ToList<Contact>();

        return tempContacts;
于 2009-10-29T13:48:22.673 に答える