Avatar billede simsen Mester
17. august 2010 - 12:04 Der er 5 kommentarer og
1 løsning

Generic forståelse

janus_007 foreslog mig i en anden tråd, jeg skulle kigge på generic caching, med reference til:

http://johnnycoder.com/blog/2008/12/10/c-cache-helper-class/

Dette har jeg så gjort + googlet en del....Nu vil jeg så gerne bekræftes/afkræftes i om jeg har forstået det korrekt + et par spørgsmål omkring ting, jeg ikke lige fatter en meter af i forbindelse med (constrained) generics:

Jeg tager udgangspunkt i følgende generic metode:

public static void Add<T>(T o, string key)
    {
        // NOTE: Apply expiration parameters as you see fit.
        // I typically pull from configuration file.

        // In this example, I want an absolute
        // timeout so changes will always be reflected
        // at that time. Hence, the NoSlidingExpiration.
        HttpContext.Current.Cache.Insert(
            key,
            o,
            null,
            DateTime.Now.AddMinutes(1440),
            System.Web.Caching.Cache.NoSlidingExpiration);
    }

Generic metoder er metoder, hvor du ikke aner hvad typen er, du arbejder med ind i metoden. Altså i ovennævnte tilfælde, kan jeg f.eks. tage et dataset eller en datatabel - eller for den sags skyld en image ind i metoden og så cacher den den type der nu engang puttes ind?

Det der bestemmer om en metode er generic er <T> og at inputtet så er af typen T -> (T o, string key)?

Jeg har så læst mig til, at man kan lave overloads til en generic metode, der bestemmer typen noget i stil med:

public static void Add<T>(T o, string key)
    {
        SubAdd(o)
    }

void SubAdd<T>(T t);
void SubAdd(DataSet t);
void SubAdd(DataDataTable t);

Nu er mit spørgsmål - er det ikke unødvendigt - så kunne man vel lige så godt lave almindelige overloads metoder istedet? Det smarte er vel, at det ikke er type bestemt?

I det link Janus gav mig, ser det for mig ud som om, han implementerer det i selve web projektet. Vil det ikke være smartest at gemme det i ny projekt, som ligger mellem DAL projektet og så Web projektet som janus_007 skrev til mig i tråden: http://www.eksperten.dk/spm/916383 ?

Nu kommer vi så til constrained:

public static void Add<T>(T o, string key) where T : class
    {
        // NOTE: Apply expiration parameters as you see fit.
        // I typically pull from configuration file.

        // In this example, I want an absolute
        // timeout so changes will always be reflected
        // at that time. Hence, the NoSlidingExpiration.
        HttpContext.Current.Cache.Insert(
            key,
            o,
            null,
            DateTime.Now.AddMinutes(1440),
            System.Web.Caching.Cache.NoSlidingExpiration);
    }

Det jeg har forstået her (tror jeg), er at det betyder, man kan afgrænse en generic metode til at være en bestemt type?

Men så hører min forståelse også op - for jeg fatter nada og nix af hvorfor at typen skal være class -> where T : class

Hvis det i min verden skulle have nogen type - så ville det da f.eks. være DataSet eller DataTabel..... Men igen, så fatter jeg ikke, hvad den skal gøre godt for - da det jo så bare kunne være en almindelig metode.....

Nogen der på simsen'sk kan forklare, hvad det betyder?

mvh
simsen :-)
Avatar billede Syska Mester
17. august 2010 - 12:17 #1
Flere ting ...

Overloads, ja, du kan lave dem, men du kan ikke kalde dem fra din generic metode, da du ikke aner hvad type det er før efter run time.

Så dette ville ikke give nogen mening:
public static void Add<T>(T o, string key)
    {
        SubAdd(o)
    }

void SubAdd<T>(T t);
void SubAdd(DataSet t);
void SubAdd(DataDataTable t);

Eller jo, den ville kalde SubAdd<T>(T t); men så har du ikke din key, og ja, så er hele den metoder ikke meget værd længere.


Ja, du kan godt lave det som et nyt project og lade dit DAL bruge det, men så skal du jo til at vide hvad for nogen ting du vil cache, det er måske nemmere at håndtere andre steder.

Det med constraints på generics kan bruges hvis du ved hvad base type du vil modtage. Forstil dig følgende:
public abstract class Base
    {
        public string Name { get; set; }
    }

    public class Div : Base
    {
       
    }

et andet sted er der en Method:
public void GetName<Value>(Value value) where Value : Base
        {
            Console.WriteLine(value.Name);
        }

Hvis du ikke angiver at det skal være af en Base Type, så vil du ikke kunne hente den Name property ud inde i den metode.

Div div = new Div();
GetName<Div>(div);

eller bare:
GetName(div);

Da compileren er klog nok til at selv finde type på compile time, så de 2 måder at kalde GetName på giver det samme.

Håber det giver mening ...
Avatar billede simsen Mester
17. august 2010 - 12:47 #2
Jeg vil ikke benytte DAL'en....min tanke er (såvidt jeg har forstået Janus korrekt så det bliver ordentligt):

Portal                  Portal.WebHelpers
|
Portal.Library
|
Portal.Caching
|
Portal.Web

I Portal.WebHelpers vil jeg have mine generic metoder, til at insert/delete/get cache (og med tiden også andre ting, der KUN er web baseret, så min Portal projekt kan bruges i andre sammenhænge)

Portal.Caching er så bindeledet mellem Portal.Library (min DAL) og Portal.Web. I den tager jeg så stilling til om den skal insert/delete/get cache eller ej. Så projektet bliver en slags bindeled mellem Portal.Web og Portal.Library, der så benytter metoderne fra Portal.WebHelpers hvis caching. Var det ikke det, Janus skrev, var den bedste måde?

Mht. constrained - så fatter jeg vist ikke så meget mere - men det er vel heller ikke nødvendigt for mig til det her med at lave en cache helper class? (skal nok huske på, at læse op på det, når jeg har lidt mere styr på generic).

Smid et svar og pointsene er dine og endnu engang tak for hjælpen :-)
Avatar billede Syska Mester
17. august 2010 - 13:03 #3
Hej,

Jeg står selv lidt i din sutiation, og har derfor også læst lidt omkring det.

Jeg tror jeg ender med er at lave et ICache interface med de metoder der nu skal bruges, og så mangler jeg bare at finde en smart/dynamisk måde at lave min cache på, så jeg nemt kan slå det fra og til. Måske via noget web.confg/app.settings

Den ICache bliver så injected i mit Repository, da projektet ikke er MEGA stort.

Jeg kan så lave forskellige implementeringer alt efter hvad jeg vil ... kunne helt bypass min ICache, dvs.

public class ByPassCache : ICache
{}

public class HttpContextCache : ICache
{}

Osv, det tror jeg kan blive rimelig smart, og kan forhåbelig spare mig for en masse linjer kode. Og så måske ikke, da man også kunne bruge din ide. Men i min verden, synes jeg det er måske at lave sit Cache lag, for så at cache laget skal kalde videre ned i DAL Laget ... derfor jeg vil have min Cache som en del af mit DAL lag :-) Så kom der også en begrundelse på det.

Eventuelt kan du måske på min blog se en post omkring det, hvis jeg får tid til det, og jeg synes det er en smart måde at lave det på :-)

mvh
Avatar billede simsen Mester
17. august 2010 - 17:09 #4
buzz

Jamen der er jo heller ikke nogen problemer, sålænge man ved med sikkerhed, at DAL laget ikke skal bruges til andet end web.

Mht. at slå det fra/til har jeg lagt det ind i appSettings i web.config filen - så ja - at det er mega nemt at slå til/fra alt efter, hvordan det nu går med UnoEuro....

ICache interface har jeg så ikke kigget på endnu - Rom blev ikke bygget på én dag for mit vedkommende - kigger på det senere. Og hører bestemt også gerne dine erfaringer om det, når du har implementeret det :-)
Avatar billede simsen Mester
17. august 2010 - 17:09 #5
Hov - og så læg så det svar tak *griner*
Avatar billede Syska Mester
17. august 2010 - 17:52 #6
ups, her kommer det svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester