Monthly Archives: February 2007

Reflector 5.0 beschikbaar

Reflector is een heerlijke tool waarmee je dde code kunt bekijken in asemblies, ook de System… assmeblies van Microsoft (heeeel leerzaam). Als je Reflector nog niet kent, haast je naar http://www.aisto.com/roeder/dotnet/ om ‘m te downloaden. Ken je ‘m wel al, haast je dan ook naar http://www.aisto.com/roeder/dotnet/ (of doe Check for Updates in je huidige versie).

TIP: Beperk het gebuik van “public”

Het is heel gewoon om classes in een library public te maken, maar eigenlijk is dit helemaal niet handig. Dat betekent namelijk dat de class vanuit alle code die de library gebruikt beschikbaar is. Met andere woorden de class maakt onderdeel uit van de interface van de library. Er zijn meerdere redenen waarom dit onwenselijk is:



  1. De interface is onnodig groot en voor gebruiker van de library kan het daarom onduidelijk zijn welke classes gebruikt moeten worden.

  2. Het is veel lastiger om te achterhalen welke verbindingen er bestaan tussen de library en eventuele clients. Dit is bijvoorbeeld lastig bij refactoring.

  3. Het is in een client mogelijk om een sub-class te maken, terwijl dit wellicht niet de bedoeling is.

Veel beter is om classes internal te maken. Dit is ook standaard zo als je geen access modifier plaatst. Daarmee zijn classes alleen beschikbaar voor code binnen dezelfde assembly (tenzij men reflection gebruikt).


Het is verstandig om opo dezelfde manier even stil te staan bij class members. Die zijn standaard private, en als je dat verandert kun je ze protected (alleen beschikibaar voor de class zelf en sub-classes), internal, protected internal (protected of internal) of public maken. Als je dit consequent toepast kun je ook reflection tegengaan door de class te markeren met [ReflectionPermission(SecurityAction.Deny)]. Daarmee is de boel niet alleen veel handiger, maar ook veel veiliger.

TIP: Centraliseer sessiedata

Ik zie in code geregeld dat het Session object op allerlei plaatsen gebruikt wordt, met name in pagina’s en controls, als volgt:


public void Page_Load(object sender, EventArgs e)
{
    Session[“MySessionVar”] += 1;
}

public void Page_PreRender(object sender, EventArgs e)
{
    Label1.Text = Session[“MySessionVar”].ToString();
}


Dit is om meerdere redenen niet aan te raden:



  1. Omdat de collectie loosely typed is, is er geen compile-time check bij het benaderen van de elementen in de collectie. Het is daarom heel makkelijk om een typfoutje te maken, waardoor je tegen het verkeerde object aan praat.

  2. Door elementen in het Session object te stoppen in de pagina, is er geen centrale administratie van de namen (keys) die in gebruik zijn.

Je kunt beide zaken oplossen door een centraal object te maken waarmee je de elementen in het Session-object benaderd, als volgt:


/// <summary>
/// Strongly typed toegang tot Session-object.
/// </summary>
internal static class TypedSession
{
   public static int MySessionVar
   {
      get
      {

         object o = 
HttpContext.Current.Session[“MySessionVar”];
         if(o == null) return 0;

         return (int)o;
      }
      set
      {
         HttpContext.Current.Session[“MySessionVar”] = value;
      }
   }
}


public void Page_Load(object sender, EventArgs e)
{
TypedSession.MySessionVar += 1;
}

public void Page_PreRender(object sender, EventArgs e)
{
Label1.Text = TypedSession.MySessionVar.ToString();
}


Merk op dat bij de get-accessor eerst gekeken wordt of het object null is. Dit is nodig omdat een int niet null mag zijn. Voor objecten waarvoor dat wel mag kun je desondanks besluiten dat er een standaardwaarde moet zijn, bijvoorbeeld een nieuw object.


Deze methodiek werkt ook uitstekend voor de Request.QueryString collectie en meer van dat soort collecties die je normaal gezien loosely typed gebruikt. Die zal je niet zo snel centraliseren, omdat het juist op een bepaalde pagina van toepassing is, maar daarmee strongly typed kunnen werken is nog steeds minder foutgevoelig. Bovendien hoeft de ontwikkelaar niet te weten waar de data vandaan komt.