20

これはおそらくばかげた質問ですが、私は匿名オブジェクトを次のViewBagように詰め込もうとしています。

ViewBag.Stuff = new { Name = "Test", Email = "user@domain.com" };

次のようなビューからアクセスします。

@ ViewBag.Stuff.Name

ViewBagは動的であり、「Stuff」は匿名オブジェクトであることを理解しています...しかし、上のView行からデバッガーを見ると、適切な値を持つすべてのプロパティを確認できます。なぜモデルバインダーはこれでそんなに苦労するのですか?

モデルクラスを作成せずにこれを達成するための良い方法はありますか?使い続けたいnew {}

4

4 に答える 4

10

基本的に問題は、匿名型が内部として生成され(回答を参照)、ビューからオブジェクトのプロパティへのハード型の参照が不可能になることです。この記事では、より詳細な説明を提供します。

http://www.heartysoft.com/anonymous-types-c-sharp-4-dynamic

Dynamic Anonymousラッパークラス(@Dakillの回答)を使用して達成することは可能ですが、醜く速くなり、プログラマーになぜそうするのか疑問を投げかける必要があります。

于 2012-01-23T23:47:36.413 に答える
5

一般に信じられていることとは異なり、これは可能ですが、やや醜いハックが必要であり、今後のメンテナンスの問題につながります。匿名オブジェクトを動的オブジェクトに「ラップ」するクラスを作成する必要があります。少し前に演習として作成しました。以下はラッパークラスのコードです。..のように使用しViewBag.Stuff = new DynamicAnonymous(new { Name = "Test", Email = "user@domain.com" });ます。

public class DynamicAnonymous : DynamicObject
{
            object obj;

            public DynamicAnonymous(object o)
            {
                    this.obj = o;
            }

            public override IEnumerable<string> GetDynamicMemberNames()
            {
                    return obj.GetType().GetProperties().Select(n => n.Name);
            }

            public override bool TryGetMember(GetMemberBinder binder, out object result)
            {
                    var prop = obj.GetType().GetProperty(binder.Name);
                    if (prop == null)
                    {
                            result = null;
                            return false;
                    }
                    else
                    {
                            result = prop.GetValue(obj, null);
                            return true;
                    }
            }

            public override int GetHashCode()
            {
                    return obj.GetHashCode();
            }

            public override string ToString()
            {
                    return obj.ToString();
            }

            public override bool Equals(object obj2)
            {
                    return obj.Equals(obj2);
            }                
 }
于 2012-01-24T01:03:57.680 に答える
2

Jsonを使用してそれをうまく達成できます

コントローラー:オブジェクト-> json文字列、ビュー:Json文字列->オブジェクト

シーンリオは、単純にコントローラークラスがC#オブジェクトをjson文字列にシリアル化し、後でビューがこの文字列を受信して​​オブジェクトに逆シリアル化します。

コントローラ内:

using Newtonsoft.Json;
ViewBag.Stuff = JsonConvert.SerializeObject(new { Name = "Test", Email = "user@domain.com" });

ビューで :

@using Newtonsoft.Json
<p>@JsonConvert.DeserializeObject(ViewBag.Stuff).Name</p>

注:これはAsp.Net Core 2.2でテストされています。そのリンクを確認して、Newtonsoft.Jsonをインストールしてください。

于 2019-01-13T20:29:59.130 に答える
0

NothingsImpossibleのメカニズムを使用してこれを行うことができますが、ExpandoObjectを使用して独自のラッパーを実装する必要はありません。次に例を示します。

var items = _repository.GetItems()
    .Select(og => {
        dynamic eo = new System.Dynamic.ExpandoObject();
        eo.Id = item.Id;
        eo.FriendlyName = og.FriendlyName;
        eo.Selected = itemIds.Contains(item.Id);
        return eo;
    })
    .ToArray();
ViewBag.Items = items;
于 2017-01-27T08:28:47.260 に答える