匿名オブジェクトを表示に渡す



アイデアは、新しい、より便利な動的構文を持つモデルを使用することです。 ここでの主な制限は、匿名型には内部アクセス修飾子があるため、匿名オブジェクトをモデルとして渡すことはできないということです。





コントローラーでこのコードを書き込もうとしているとします:



public class HomeController : Controller

{

public ActionResult Index()

{

return View(

new

{

Message = "Welcome to ASP.NET MVC!" ,

Date = DateTime .Now

});

}

}



* This source code was highlighted with Source Code Highlighter .








モデルに匿名オブジェクトを渡していることに注意してください。 これの主な理由は、必要な外部ViewModelタイプの作成を避けるためです。 明らかに、これは多少議論の余地がありますが、そのような代替案よりも簡単に見えるはずです。



ViewData[ "Message" ] = "Welcome to ASP.NET MVC!" ;

ViewData[ "Date" ] = DateTime .Now;

return View();



* This source code was highlighted with Source Code Highlighter .








次に、ビューを変更して、

Inherits= "System.Web.Mvc.ViewPage<dynamic>"



* This source code was highlighted with Source Code Highlighter .








理想的には、これにより次のような記述ができるはずです。



< asp:Content ID ="indexContent" ContentPlaceHolderID ="MainContent" runat ="server" >

< h2 > <% = Model.Message %> </ h2 >

< p >

The date is <% = Model.Date %>

</ p >

</ asp:Content >



* This source code was highlighted with Source Code Highlighter .








しかし、デフォルトでは、動的バインダーはこれを許可しません!



残念ながら、このコードを実行しようとすると、次のようになります。

エラー:Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: '<> f__AnonymousType1 <string、System.DateTime> .Message'は保護レベルのためアクセスできません

これは、コントローラーの匿名型が内部であるため、定義されているアセンブリからのみアクセスできるためです。 ビューは個別にコンパイルされるため、動的バインダーは、このアセンブリを超えることができないと文句を言います。 しかし、非常に簡単に、プライベートリフレクションを介してバインドするDynamicObjectを作成できます。



ここでは、DynamicObjectだけでなく、それを使用するDynamicViewPageも作成します。 完全な実装は次のとおりです。



public class DynamicViewPage : ViewPage {

// dynamic

public new dynamic Model { get ; private set ; }



protected override void SetViewData(ViewDataDictionary viewData) {

base .SetViewData(viewData);



// , private

Model = new ReflectionDynamicObject() { RealObject = ViewData.Model };

}



class ReflectionDynamicObject : DynamicObject {

internal object RealObject { get ; set ; }



public override bool TryGetMember(GetMemberBinder binder, out object result) {

//

result = RealObject.GetType().InvokeMember(

binder.Name,

BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,

null ,

RealObject,

null );



// true, InvokeMember , -

return true ;

}

}

}



* This source code was highlighted with Source Code Highlighter .








ご覧のとおり、ここではすべてが簡単です。 必要なのは、プライベートリフレクションを使用してプロパティの値を調べることだけです。 それだけです。Viewの基本クラスとしてこれを使用するだけです。

<%@ Page Language = "C#" MasterPageFile = "〜/ Views / Shared / Site.Master" Inherits = "MvcHelpers.DynamicViewPage"%>






All Articles