ASP.NET MVC 2.0 & .NET 4.0 – ExpandoObject
Jag har tidigare skrivit om ett nytt objekt i .NET 4.0, kallat ExpandoObject (http://weblogs.asp.net/mikaelsoderstrom/archive/2009/10/06/skapa-objekt-med-data-dynamiskt-med-expandoobject.aspx). Det är ett objekt som finns under System.Dynamic och som låter utvecklaren själv sätta egenskaper och metoder direkt på det istället för att skapa upp en separat klass.
Vid vissa tillfällen så är det överflödigt att skapa upp en ny klass då man ändå bara ska använda objektet på ett enda isolerat ställe, och då kan det vara smidigare att skapa upp ett dynamiskt objekt som skickas iväg direkt.
Ett scenario där man kan vilja skapa upp dynamiska objekt är i controllers i ASP.NET MVC. Oftast så är det specifika modeller för de specifika vyerna, vilket gör att det kan vara svårt att använda samma modell till flera vyer (om man inte vill ha extra egenskaper förstås). Genom att använda ExpandoObject här så kan vi skapa upp en ny modell för den aktuella vyn och returnera direkt.
Till att börja med så måste vi ha Visual Studio 2010 då det kräver .NET 4.0. Vi skapar upp ett ASP.NET MVC 2.0-projekt och lägger till en ActionResult-metod i HomeController med namnet ”DynamicView”. Allt är än så länge helt standard.
Då vi vill ha en dynamisk metod så kommer vi att börja med att skapa upp en instans av List<dynamic>. Anledningen till att det är av typen dynamic är för att vi måste ha en dynamisk instans av ExpandoObject för att kunna lägga till de egenskaper och metoder vi vill ha.
Action-metoden kommer att se ut så här:
public ActionResult DynamicView()
{
List<dynamic> customers = new List<dynamic>();
dynamic Mikael = new ExpandoObject();
Mikael.Name = "Mikael";
Mikael.Age = 24;
Mikael.PrintAge = new Func<int, string>(a => a.ToString() + "år gammal");
customers.Add(Mikael);
dynamic Bill = new ExpandoObject();
Bill.Name = "Bill";
Bill.Age = 54;
Bill.PrintAge = new Func<int, string>(a => a.ToString() + " years old");
customers.Add(Bill);
return View(customers);
}
Det som sker här är att två dynamiska objekt av typen ExpandoObject skapas upp. De får sedan två egenskaper, ”Name” och ”Age”. Utöver det så får de även en varsin metod ”PrintAge” som skriver ut åldern. Värt att notera är att det är två olika Func<T1, T2>, den första skriver ut det på svenska, och den andra på engelska. De här metoderna kommer att vara specifika för de enskilda dynamiska objekten.
Till sist så lägga objekten i en List<dynamic> som sedan returneras.
För att se resultat så måste vi skapa upp en vy som kan visa dessa. Vyn som skapas upp ska ha modellen ”System.Collections.Generic.List<dynamic>”. Till skillnad från statiska typer så får vi inte upp våra egenskaper direkt på sidan, utan vi måste istället skriva ut dem manuellt.
För att få fram namn och ålder kan vi skriva precis som om det vore en statisk modell:
<h2>DynamicView</h2>
<ul>
<% foreach (dynamic item in Model) { %>
<li><%= item.Name %>, <%= item.Age %></li>
<% } %>
</ul>
Vi har dock en metod ”PrintAge” som tar emot åldern och skriver ut den. Genom att ändra koden ovan till nedanstående så får vi ut texten på två olika språk:
<h2>DynamicView</h2>
<ul>
<% foreach (dynamic item in Model) { %>
<li><%= item.Name %>, <%= item.PrintAge(item.Age) %></li>
<% } %>
</ul>
Resultat:
Genom att använda dynamiska typer så är vi inte bunden till någon specifik typ, utan vi kan använda vilken dynamisk ActionResult-metod som helst så länge som den returnerar ett objekt med dessa egenskaper och metoder.