Iteam
GitHub

Method extensions för Episerver

När C# 3.0 släpptes i samband med dotnet 3.5 i november 2007 kom så många nya bra grejer, t.ex. LINQ, att det var lätt att missa andra små godbitar som method extensions. Method extensions är ett sätt att lägga till nya metoder i en klass, utan att ändra i klassens egen cs-fil eller blanda in partiella klasser eller något sånt.

Vi tar ett exempel: Episerver har många bra funktioner, men definitivt inte alla man önskar sig och inte heller alltid där man vill ha dom.

Istället för att t.ex skriva DataFactory.Instance.GetChildren(page) skulle vi vilja skriva page.GetChildren() och vi vill också kunna skriva page.GetSiblings(). Inte för att det tillför ny funktionalitet, men för att det vore praktiskt. En lösning skulle kunna vara att göra en egen subklass till PageData med de här metoderna, men det betyder att man måste instantiera din egen klass varenda gång du ska använda t.ex. CurrentPage-objektet. Att istället använda method extensions för att få till den här lösningen tar bara några minuter och ger garanterat en liten endorfinkick (samt att du kommer att spendera hela eftermiddan med att skapa alla de nya metoder du drömt om skulle finnas på de klasser du använder).

Hittills har vi implementerat funktionalitet som GetSiblings som en metod i ett klassbibliotek, men det är lätt att glömma bort vad dom heter, och var metoderna finns.

Med hjälp av extension methods så får vi direkt hjälp av Intellisense - det räcker med att skriva CurrentPage, trycka punkt och få upp en fin lista där metoden GetSiblings dyker upp precis som dom inbyggda metoderna (med en liten ikon förstås). Anropet blir då ”CurrentPage.GetSiblings();” - mycket stiligt!

Det som behövs för att skapa en method extension är att metoden måste vara statisk och ligga i en statisk klass. Före den första parametern i den statiska metodenlägger man till ordet this (se exempel i koden nedan). Detta gör att den här metoden kommer att dyka upp på alla objekt av den klassen, i detta fallet PageData.

För att få tillgång till de nya metoderna krävs att man ”når” klassen, enklast med att lägga till dess namespace med using längst upp i filen precis som när man använder LINQ (där man skriver using System.Linq). Tyvärr så går det inte att göra extension properties som skulle göra det möjligt att t.ex skriva CurrentPage.Children för att komma åt alla undersidor. Vi hoppas på att detta kommer i C# 4.0 (det finns dock mängder av diskussioner varför det inte är möjligt eller en bra idé - men vi gillar tanken).

Här kommer GetSiblings i komplett form med hjälpfunktion för GetChildren, samt som bonus en generisk metod som underlättar när man har properties som pekar på andra sidor och man vill hämta ut dessa relaterade värden - alltså en sorts indirekt property. Om du inte stött på generics tidigare så har du nåt att sätta tänderna i så du slipper metoder som returnerar object som måste konverteras och castas.

Tommy Söderström
2009-03-06