MVC中ViewBag可以设置任意自定义的属性,也可以读取出来。
如下面这样在controller的action方法中设置了ViewBag的一个Entires属性(该属性名字任意取)后,在相应的view中也可以读取出来,那这是怎样做到的呢?
public ActionResult Index() { var mostrecentEntiries = (from m in dbContext.test orderby m.ID descending select m).Take(10); ViewBag.Entires = mostrecentEntiries; return View(); }
先来看ViewBag是个什么东西?ViewBag在ControllerBase类中的定义如下:
[Dynamic] public object ViewBag { [return: Dynamic] get { Func<ViewDataDictionary> viewDataThunk = null; if (this._dynamicViewDataDictionary == null) { if (viewDataThunk == null) { viewDataThunk = delegate { return this.ViewData; }; } this._dynamicViewDataDictionary = new DynamicViewDataDictionary(viewDataThunk); } return this._dynamicViewDataDictionary; } }
看出来了,他其实是一个DynamicViewDataDictionary类型,而DynamicViewDataDictionary得类型定义又如下:
internal sealed class DynamicViewDataDictionary : DynamicObject { // Fields private readonly Func<ViewDataDictionary> _viewDataThunk; // Methods public DynamicViewDataDictionary(Func<ViewDataDictionary> viewDataThunk) { this._viewDataThunk = viewDataThunk; } public override IEnumerable<string> GetDynamicMemberNames() { return this.ViewData.Keys; } public override bool TryGetMember(GetMemberBinder binder, out object result) { result = this.ViewData[binder.Name]; return true; } public override bool TrySetMember(SetMemberBinder binder, object value) { this.ViewData[binder.Name] = value; return true; } // Properties private ViewDataDictionary ViewData { get { return this._viewDataThunk(); } }
关键就是实现了上述两个绿色的方法,我们自己也来模拟一个这样的效果看,只需自定义一个继承了DynamicObject的类并重写TrySetMember,TryGetMember两个方法即可实现ViewBag同样的效果:
class myDynamic : DynamicObject { Dictionary<string, object> ViewData; public override bool TrySetMember(SetMemberBinder binder, object value) { this.ViewData[binder.Name] = value; return true; } public override object TryGetMember(GetMemberBinder binder, object value) { return this.ViewData[binder.Name]; } } protected void Application_Start() { dynamic myDynamic = new myDynamic(); myDynamic.Data = "aaa"; string stra = myDynamic.Data;