Avatar billede iluka Nybegynder
27. maj 2009 - 14:14 Der er 20 kommentarer og
1 løsning

Return generic

hej eksperten

Jeg kunne godt tænke mig at lave en metode der piller en værdi ud af et xml dokument og returnerer det som den type der er specificeret generisk.

Xml ser abstrakt sådan her ud

<result>
  <alder>30</alder>
  <navn>iluka</alder>
</result>

og den metode jeg gerne vil lave skulle se nogenlunde sådan her ud

private T GetValue<T> (string key)
{
  string value = xmlDocument.SelectSingleNode("result/" + key).InnerText;

  if (typeof(T) == typeof(string))
    return (string)value;
  if (typeof(T) == typeof(int))
    return int.parse(value);
}

Jeg er klar over at ovenstående ikke virker, mit spørgsmål er om man kan lave noget i den retning, og hvordan.

tak,
iluka
Avatar billede kalp Novice
27. maj 2009 - 14:29 #1
private T GetValue<T> (T key)
Avatar billede kalp Novice
27. maj 2009 - 14:31 #2
ahh okay.. det ikke det du mener..

hvad med..

private T GetValue<T> (string key)
{
  string value = xmlDocument.SelectSingleNode("result/" + key).InnerText;

  return T.Parse(value);
}
Avatar billede aaberg Nybegynder
27. maj 2009 - 14:40 #3
Kalps forslag vil desværre ikke virke, da T er en generisk type, og derfor ikke vil genkende Parse metoden.

Men følgende bør virke:

private T GetValue<T>(string key)
{

  string value = xmlDocument.SelectSingleNode("result/" + key).InnerText;

  return (T)Convert.ChangeType(value, typeof(T));
}
Avatar billede kalp Novice
27. maj 2009 - 14:42 #4
jeg tror du skal gøre sådan her: (og opsi for de andre forslag)

private T GetValue<T> (string key)
{
  string value = xmlDocument.SelectSingleNode("result/" + key).InnerText;

  return (T)value;
}
Avatar billede kalp Novice
27. maj 2009 - 14:47 #5
yeps.. du har ret aaberg_bb og jeg tænkte mig heller ikke om:)
mit sidste forslag fungere dog fint.
Avatar billede aaberg Nybegynder
27. maj 2009 - 14:51 #6
Er du sikker?

Hvad hvis du kalder metoden med T som en integer? Du kan ikke caste en string til en int!

Hvis du prøver at copy/paste dit sidste foreslag ind i Visual Studio, vil den dog også sige: Cannot convert type 'string' to 'T'
Avatar billede iluka Nybegynder
27. maj 2009 - 14:57 #7
kalp: jeg kan vel ikke type caste til int?
Avatar billede iluka Nybegynder
27. maj 2009 - 15:02 #8
aaberg_cc: din løsning virker perfekt... skriv et svar så får du points!
Avatar billede kalp Novice
27. maj 2009 - 15:03 #9
iluka >>> joo da:) og det virker;) jeg testede lige med andre objekter jeg definerede selv... det virker også..

så ingen problemer der:)
Avatar billede iluka Nybegynder
27. maj 2009 - 15:06 #10
argh stadig et problem... hvis noden ikke findes, så skal jeg returnere et eller andet... int.MinValue eller noget for primitiver og null for komplekse type. hvordan så det?
Avatar billede iluka Nybegynder
27. maj 2009 - 15:10 #11
Selv fundet svaret på det sidste... default(T). My Bad. aaberg_cc's løsning accepteret, sorry kalp har ikke testet din, du får points næste gang ;)
Avatar billede kalp Novice
27. maj 2009 - 15:10 #12
tilføj:

if(typeof(T).IsPrimitive)
return int.MinValue;
else
return null;
Avatar billede iluka Nybegynder
27. maj 2009 - 15:12 #13
løsningen blev (lidt anderledes med xml documentet):

private T GetValue<T>(XmlNode node, string key)
        {
            XmlNode subnode = node.SelectSingleNode(key);
            if (node == null)
                return default(T);
            string value = subnode.InnerText;
            return (T)Convert.ChangeType(value, typeof(T));
        }

kalp: default(T) er federe, så behøver jeg ikke tilføje flere "if" for double, guid whatever.
Avatar billede kalp Novice
27. maj 2009 - 15:13 #14
det skal du heller ikke, men default er stadig bedre;o)
Avatar billede iluka Nybegynder
27. maj 2009 - 15:13 #15
faktisk blev det: (nu uden dumme fejl)

private T GetValue<T>(XmlNode node, string key)
        {
            XmlNode subnode = node.SelectSingleNode(key);
            if (subnode == null)
                return default(T);
            string value = subnode.InnerText;
            return (T)Convert.ChangeType(value, typeof(T));
        }
Avatar billede aaberg Nybegynder
27. maj 2009 - 15:22 #16
Et sidste forslag. Hvis koden som kalder metoden vil vide om noden var null, vil du få problemer med ovenstående, da default værdien er 0. Så vil du altså ikke kunne kende forskel på 0 og null.

Denne lille udvidelse vil ordne dette:

private bool GetValue<T>(XmlNode node, string key, out T value)
{
    XmlNode subnode = node.SelectSingleNode(key);

    if (subnode == null || string.IsNullOrEmpty(subnode.InnerText))
    {
        value = default(T);
        return false;
    }
    else
    {
        value = (T)Convert.ChangeType(stringVal, typeof(T));
        return true;
    }
}
Avatar billede aaberg Nybegynder
27. maj 2009 - 15:25 #17
Ovenstående vil returnere false, hvis der ikke var en værdi, og true hvis der er en værdi. Værdien returneres i output parameteren "value".

Når metoden kaldes, gøres sådan:

int value;
if (GetValue<int>(myNode, myKey, out value)
{
  //Hvis den kommer ind i denne if, var der en værdi.
}
else
{
  //Hvis den kommer ind i else-delen, var der ikke en værdi.
}
Avatar billede iluka Nybegynder
27. maj 2009 - 15:27 #18
aaberg_cc: smart ;)
Avatar billede aaberg Nybegynder
27. maj 2009 - 15:33 #19
Hvis du vil gi points, så lagde jeg et svar i mit første forslag.

:-)
Avatar billede arne_v Ekspert
28. maj 2009 - 00:48 #20
Et par kommentarer.

1)

#4 compiler ikke som forklaret i #6.

2)

Jeg kan ikke lide at bruge value som variabel navn, da det er et keyword i property set'ers.

3)

Med hensyn til:

(T)Convert.ChangeType(stringVal, typeof(T))

så er det vigtigt at forstå at den ikke virker per magi.

Den kan ikke konvertere fra hvad som helst til hvad som helst.

Den kan konvertere hvis:
- input implementerer IConvertible (det gør string)
- output eksisterer som en To metode i IConvertible (det gør int, double, bool, string etc.)
Avatar billede iluka Nybegynder
28. maj 2009 - 08:35 #21
#20
3) er en god pointe. Ulempen ved at bruge generics på denne måde er at det åbner for nogle runtime fejl jeg kunne have fanget på compile time hvis jeg havde droppet generics og lavet metoder til de typer input jeg skal konvertere. F.eks. giver det en runtime exception at fodre metoden med en Guid. Det er dog en praktisk lille metode da jeg fra Microsoft CRM's webservice får en masse værdier tilbage der typisk er guids, strings, ints, double, datetime osv. Med lidt viden om hvad jeg forventer at få tilbage fra CRM giver det her en elegant løsning på at parse resultater.

tak for hjælpen gutter, points til aaberg_cc for den første løsning der compiler ;)
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