DTO som i Data Transport Objects. Objekter der bare har en række properties, så man kan overfører data mellem DAL og BLL og mellem BLL og UI. Selvfølgelig er overførslen af data mellem de forskellige lag ikke nødvendigvis de samme objekter, og man kan sagtens have et sæt DTO’er til DAL og et andet sæt til UI. Det er bare en pinsel at vedligeholde så meget kode, som man ikke har nogen som helst brug for.
Da jeg startede med C# 1.0, kom jeg fra JavaScript ASP, og jeg må indrømme at jeg blev meget facineret af den typestærke omgang med objekter, og deraf den dejlige intelli-sense i Visual Studio. Et af de store hype emner dengang var også Typed DataSet, hvor omfanget af uberørte kodelinier var helt enormt – hvor mange har brugt dem til andet end dejlig VS.NET oplevelser.
Nu har vi heldigvis fået en masse funktionelle værktøjer, og vi har fået generics. Nu kan vi faktisk helt undvære typestærke DTO’er. Men gør vi så det? Nej – vi forsætter med kb efter kb af ligegyldig kode. Jo man kan godt nok bruge NHibernate eller andre ORM frameworks til at danne klasserne i DAL-laget, men vi er stadig bundet i transporten mellem BLL og UI, og reelt set er der jo stadig masser af ligegyldig mapningskode.
Anonyme typer kan i nogen omfang bruges som DTO’er, men det kræver at man laver lidt reflektions gymnastik på modtagersiden, for man kender jo af gode grunde ikke typen på forhånd. Det er det man gør i MVC framevorket, når man kalder den generiske dictionary på Viewdata objektet. Ikke helt godt synes jeg. Jeg har derfor ofte brugt frameworkets indbyggede Tuple: KeyValuePair. Den er kendt af både afsender og modtager, og er super fin som DTO for f.eks. listedata. Men hvad nu når man har 3 eller 4 værdier? Så kan man jo bare indlejre flere objekter:
var tripleDTO = new KeyValuePair<string ,KeyValuePair<int ,int>>();
Ikke ligefrem intuitivt, og super indviklet at initialicerer. Jeg har derfor lavet et par simpel generiske Tuple klasse, som jeg kan bruge i stedet:
///
/// Single
///
public class Tuple
{
public Tuple(T1 first)
{
this.Item1 = first;
}
public T1 Item1 { get; set; }
}
///
/// Double
///
public class Tuple : Tuple
{
public Tuple(T1 first, T2 second)
: base(first)
{
this.Item2 = second;
}
public T2 Item2 { get; set; }
}
///
/// Triple
///
public class Tuple : Tuple
{
public Tuple(T1 first, T2 second, T3 third)
: base(first, second)
{
this.Item3 = third;
}
public T3 Item3 { get; set; }
}
///
/// Quadruple
///
public class Tuple : Tuple
{
public Tuple(T1 first, T2 second, T3 third, T4 fourth)
: base(first, second, third)
{
this.Item4 = fourth;
}
public T4 Item4 { get; set; }
}
///
/// Quintuple
///
public class Tuple : Tuple
{
public Tuple(T1 first, T2 second, T3 third, T4 fourth, T5 fifth)
: base(first, second, third, fourth)
{
this.Item5 = fifth;
}
public T5 Item5 { get; set; }
}
Nu kan jeg transporterer typestærke værdisæt rundt mellem lag, uden at skulle lave hjernedøde DTO’er.
For at gøre initialiceringen lettere, har jeg lavet en statisk Tuple klasse, med facktory metoder: Create:
public static class Tuple
{
public static Tuple Create(T1 first)
{
return new Tuple(first);
}
public static Tuple Create(T1 first, T2 second)
{
return new Tuple(first, second);
}
public static Tuple Create(T1 first, T2 second, T3 third)
{
return new Tuple(first, second, third);
}
public static Tuple Create(T1 first, T2 second, T3 third, T4 fourth)
{
return new Tuple(first, second, third, fourth);
}
public static Tuple Create(T1 first, T2 second, T3 third, T4 fourth, T5 fifth)
{
return new Tuple(first, second, third, fourth, fifth);
}
}
Det giver følgende initialicering:
var quadDto = Tuple.Create(12, “Jesper”, “Jensen”, true);
Nu har jeg reduceret antallet af custom DTO’er til 0, og det er jo dejligt, når man som jeg: Hader DTO’er.
Bemærk i øvrigt at en Tuple klasse lignenede denne, kommer i c# 4.0, hvor den kan initialiceres med op til 8 værdier.
Code on…