2013-06-28 15 views
6

napisałem poniżej metody z follwing wymogu -Typowa metoda powrotu pustych typ wartości

  1. wejście jest XMLNode i attributeName
  2. Zwraca wartość, jeśli jest z powiązanej nazwy atrybutu przeszedł
  3. znaleziono
  4. Tam, gdzie nie ma wartości w attributeName, należy ją zwrócić -

    3.1. Dla int -1 3.2. Dla Datetime DateTime.MinValue 3.3. W przypadku łańcucha ciągów, nr 3.4. Dla bool, null

Poniższa metoda kończy się niepowodzeniem dla przypadku 3.4.

public T AttributeValue<T>(XmlNode node, string attributeName) 
     { 
      var value = new object(); 

      if (node.Attributes[attributeName] != null && !string.IsNullOrEmpty(node.Attributes[attributeName].Value)) 
      { 
       value = node.Attributes[attributeName].Value; 
      } 
      else 
      { 

       if (typeof(T) == typeof(int)) 
        value = -1; 
       else if (typeof(T) == typeof(DateTime)) 
        value = DateTime.MinValue; 
       else if (typeof(T) == typeof(string)) 
        value = null; 
       else if (typeof(T) == typeof(bool)) 
        value = null; 



      } 
      return (T)Convert.ChangeType(value, typeof(T)); 
     } 

Kiedy zmiana to

public System.Nullable<T> AttributeValue<T>(XmlNode node, string attributeName) where T : struct 
     { 
      var value = new object(); 

      if (node.Attributes[attributeName] != null && !string.IsNullOrEmpty(node.Attributes[attributeName].Value)) 
      { 
       value = node.Attributes[attributeName].Value; 
      } 
      else 
      { 

       if (typeof(T) == typeof(int)) 
        value = -1; 
       else if (typeof(T) == typeof(DateTime)) 
        value = DateTime.MinValue; 
       else if (typeof(T) == typeof(string)) 
        return null; 
       else if (typeof(T) == typeof(bool)) 
        return null; 



      } 
      return (T?)Convert.ChangeType(value, typeof(T)); 
     } 

To nie dla typu string tj przypadku 3,3

szuka pomocy przodu.

+0

Jak uruchomić metodę w swoim pierwszym zbiorze? Musiałbyś nazwać to jako 'AttributeValue (...)' Jeśli po prostu wywołasz 'AttributeValue (...)' to 'null' nie jest poprawną wartością' bool'. EDYCJA: A twoja druga sprawa kończy się niepowodzeniem, ponieważ 'ciąg' nie może być użyty dla' System.Nullable 'ponieważ' string' nie jest strukturą typu wartości. –

Odpowiedz

4

dzięki za liczby odpowiedzi, to co napisałem i działa dla mnie ..

Zwraca null dla typów.

public T AttributeValue<T>(XmlNode node, string attributeName) 
     { 
      object value = null; 

      if (node.Attributes[attributeName] != null && !string.IsNullOrEmpty(node.Attributes[attributeName].Value)) 
       value = node.Attributes[attributeName].Value; 

      if (typeof(T) == typeof(bool?) && value != null) 
       value = (string.Compare(value.ToString(), "1", true) == 0).ToString(); 

      var t = typeof(T); 
      t = Nullable.GetUnderlyingType(t) ?? t; 

      return (value == null) ? 
       default(T) : (T)Convert.ChangeType(value, t); 
     } 

Ja nazywam to jak ten

const string auditData = "<mydata><data><equipmentStatiticsData><userStatistics maxUsers='100' totalUsers='1' authUsers='0' pendingUsers='' adminAddedUsers='' xmlUsers='' internalDBUsers='' webUsers='' macUsers='' vpnUsers='' xUsers8021=''></userStatistics><equipmentStatistics cpuUseNow='14' cpuUse5Sec='1' cpuUse10Sec='1' cpuUse20Sec='1' ramTotal='31301632' ramUtilization ='1896448' ramBuffer='774144' ramCached='8269824' permStorageUse='24' tempStorageUse='24'></equipmentStatistics><authStatus status='1'></authStatus></equipmentStatiticsData></data></mydata>"; 
    xmlDoc.LoadXml(auditData); 
    var userStatsNode = xmlDoc.SelectSingleNode("/mydata/data/equipmentStatiticsData/userStatistics"); 


    var intNullable = AttributeValue<int?>(userStatsNode, "vpnUsers"); 
    var nullableBoolTrue = AttributeValue<bool?>(userStatsNode, "totalUsers"); 
    var nullableBoolFalse = AttributeValue<bool?>(userStatsNode, "authUsers"); 
    var nullableString = AttributeValue<string>(userStatsNode, "authUsers"); 
    var pendingUsersBoolNull = AttributeValue<bool?>(userStatsNode, "pendingUsers"); 
    var testAttribNullableNotFoundDateTime = AttributeValue<DateTime?>(userStatsNode, "testAttrib"); 
    var testAttrib1NullString = AttributeValue<string>(userStatsNode, "testAttrib"); 
    var maxUsersNullInt = AttributeValue<int?>(userStatsNode, "maxUsers"); 

to działa dobrze dla mnie. dzięki ludziom ...

+0

Mam się dobrze z otrzymywaniem wartości null z powrotem teraz. to wygląda na lepsze rozwiązanie, – Ashish

5

Dla wersji 3.4 należy użyć bool? jako typu dla T, więc można zwrócić wartość null.

Następnie można użyć słowa kluczowego default dla 3.3 i 3.4 (string i bool?). Zgodnie z msdn zwróci null dla typów odniesienia i wartości domyślnej dla typów wartości (takich jak int lub bool).

Można go używać jak

return default(T); 
+0

Wymagania dla przypadku 'bool' (3.4) polegają na tym, że zwraca' null'. To zwróci wartość 'false' i nie będzie możliwe odróżnienie od przypadku, w którym nie znaleziono żadnego pasującego atrybutu, oraz przypadku, w którym podano" false ". –

+0

Nie musisz tego używać, używając 'bool?' Jako ogólnego argumentu, zwracając w tym przypadku wartość zerową? Mam na myśli, jeśli T jest 'bool' nie możesz zwrócić false, więc musisz użyć' bool? '... –

+0

tylko po to, aby wyjaśnić, domyślnie (T) dla' bool? 'Zwróci null –

0

Musisz zadzwonić do pierwszego zestawu kodu przy użyciu bool? nie bool ponieważ null nie jest prawidłową wartością dla nie-wartości pustych bool.

Twój drugi blok kodu powiodło się, ponieważ nie można używać string dla generycznego typu Nullable<T> ponieważ wymaga typu wartości struct i string jest klasa referencyjna typu.

Musisz zmienić swój pierwszy blok metody szukać typeof(bool?) i wywołać go z wartości pustych typu boolean:

public T AttributeValue<T>(XmlNode node, string attributeName) 
{ 
    var value = new object(); 

    if (node.Attributes[attributeName] != null && !string.IsNullOrEmpty(node.Attributes[attributeName].Value)) 
    { 
     value = node.Attributes[attributeName].Value; 
    } 
    else 
    { 
     if (typeof(T) == typeof(int)) 
      value = -1; 
     else if (typeof(T) == typeof(DateTime)) 
      value = DateTime.MinValue; 
     else if (typeof(T) == typeof(string)) 
      value = null; 
     else if (typeof(T) == typeof(bool?)) 
      value = null; 
    } 

    var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); 
    return (T)Convert.ChangeType(value, type); 
} 

następnie wywołać ją jako:

bool? value = AttributeValue<bool?>(node, "myAttributeName"); 

Trzeba także wykonaj sprawdzenie, ponieważ Convert.ChangeType nie będzie działało dla typu zerowego. Szybka naprawa z here rozwiązuje to.(To jest wliczone w powyższym kodzie)

EDIT: Tutaj jest ulepszony/wersja czyszczony od wybranej metody:

public T AttributeValue<T>(XmlNode node, string attributeName) 
{ 
    if (node.Attributes[attributeName] != null && !string.IsNullOrEmpty(node.Attributes[attributeName].Value)) 
    { 
     var value = node.Attributes[attributeName].Value; 
     var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); 
     return (T)Convert.ChangeType(value, type); 
    } 
    else 
    { 
     if (typeof(T) == typeof(int)) 
      return (T)(object)(-1); 

     return default(T); 
    } 
} 

Możesz dodać dodatkowe szczególne przypadki dla nieistniejących węzłów, ale wszystkie sprawy z wyjątkiem int są już domyślną wartością dla typów, więc zamiast tego użyj po prostu default(T).

Powiązane problemy