4

なぜ今初めてこの振る舞いに気づいたのかわかりません。これが設計された動作であるかどうか、または何かが足りないかどうかを確認するために探しています。

を実装しIEnumerable<T>、追加のプロパティを提供するビューモデルがあるとします。例えば:

public class MyResultsViewModel : IEnumerable<MyResultViewModel>
{
    public IEnumerable<MyResultViewModel> Results { get; set; }
    public string SomeAdditionalProperty { get; set; }

    public IEnumerator<MyResultViewModel> GetEnumerator()
    {
        return Results.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator; }
}

このモデルをjsonとして返すコントローラーもあるとします。例えば:

public ActionResult MyResults()
{
    var entities = PrivateMethodToGetEntities();
    var models = Mapper.Map<MyResultsViewModel>(entities);
    models.SomeAdditionalProperty = "I want this in the JSON too";
    return Json(models, JsonRequestBehavior.AllowGet);
    // models now contains a populated Results as well as the add'l string prop
}

クライアントでJSONリクエストから結果を取得すると、常に配列として返されます。例えば:

$.get('/Path/To/MyResults')
.success(function (results) {
    alert(results.SomeAdditionalProperty); // this alerts 'undefined'
    alert(results.length); // this alerts the size / count of Results
    alert(results[0]); // this alerts object
    // inspecting results here shows that it is a pure array, with no add'l props
});

ビューモデルを実装しないようにリファクタリングする前にIEnumerable<T>、これが仕様によるものであり、予期されるものであることを確認したいと思います。追加のプロパティに対応するためにjavascript配列オブジェクトのプロトタイプを拡張する必要があるため、これは理にかなっていると思います。

アップデート:

内部列挙可能オブジェクトに名前を付けないように、ビューモデルに次の変更を加えましたResults

public class MyResultsViewModel : IEnumerable<MyResultViewModel>
{
    public IEnumerable<MyResultViewModel> NotNamedResults { get; set; }
    public string SomeAdditionalProperty { get; set; }

    public IEnumerator<MyResultViewModel> GetEnumerator()
    {
        return NotNamedResults.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator; }
}

この変更により、動作は維持されます。alert(JSON.stringify(results))列挙されたMyResultViewModelsのコレクションに対して通常の配列構文を生成します。

[{"ResultProp1": "A"、 "ResultProp2": "AA"、 "ResultProp3": "AAA"}、{"ResultProp1": "B"、 "ResultProp2": "BB"、 "ResultProp3": "BBB "}、{" ResultProp1 ":" C "、" ResultProp2 ":" CC "、" ResultProp3 ":" CCC "}、{" ResultProp1 ":" D "、" ResultProp2 ":" DD "、" ResultProp3 ": "DDD"}、{"ResultProp1": "E"、 "ResultProp2": "EE"、 "ResultProp3": "EEE"}]

JsonResultコントローラアクションがを返し、jquerysuccess関数が呼び出されるまでの間に追加のプロパティが失われているようです。

4

1 に答える 1

4

IEnumerable を実装するクラスの場合、JavascriptSerializerは列挙された項目のみをシリアル化します。シリアル化するデータを取得するために呼び出しGetEnumerator()、他のプロパティは無視されます。そのため、Counta のプロパティはList<T>シリアル化されず、他のプロパティもシリアル化されません。

その理由は、このタイプの構造は json 形式で表すことができないためです。他のプロパティを含めるには、シリアライザーは配列ではなくハッシュ オブジェクトを作成する必要がありますが、厳密に言えば、ハッシュ オブジェクトはコレクションではありません。(例外は、ハッシュ オブジェクトとしてシリアル化される のようなキーと値のペアのクラスDictionaryです。ただし、列挙された辞書エントリのみがシリアル化されるという規則が成り立ちます)。

IEnumerableしかし、これを行う代わりに、json としてシリアル化するために直接実装するクラスを作成するのはなぜですか?

 public class MyResultsViewModel {
     public IEnumerable<MyModel> Models{ get; set; }
     public String SomeAdditionalData { get; set; } 
 }
于 2012-08-10T20:35:22.860 に答える