Хранение анонимного объекта в ViewBag

Это, вероятно, глупый вопрос, но я пытаюсь засунуть анонимный объект в ViewBag вот так:

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

и получить доступ к нему из вида, как так:

@ViewBag.Вещи.Имя

Я понимаю, что ViewBag динамичен, и что" материал " является анонимным объектом... но когда я смотрю с отладчиком из строки представления выше, я вижу все свойства с соответствующими значениями. Почему модельное связыватель имеет такое трудное время с это?

есть хороший способ сделать это без создания класса модели? Я хочу продолжить использовать new {}

3 ответов


по существу проблема заключается в том, что анонимные типы генерируются как внутренние (ответ), делая жесткие типизированные ссылки на свойство объекта невозможными из представления. Эта статья дает более подробное объяснение:

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

Это можно сделать с использованием класса динамической анонимной оболочки (ответ@Dakill), но становится уродливым быстро и должен сделать программист задается вопросом, почему он это делает.


Вопреки распространенному мнению, это можно сделать, но включает в себя несколько уродливый хак, который приведет к проблемам обслуживания по дороге.. Он включает в себя запись класса, чтобы "обернуть" ваш анонимный объект в динамический объект. Я сделал это как упражнение некоторое время назад, Ниже приведен код класса-оболочки, вы бы использовали его как 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);
            }                
 }

вы можете сделать это с помощью механизма NothingsImpossible descibed, но без реализации собственной оболочки с помощью 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;