2013-06-28 19 views
6

ho scritto qui di seguito il metodo con il requisito follwing -metodo generico per tornare Nullable Tipo Valori

  1. ingresso è xmlnode e attributeName
  2. di ritorno il valore se si trova con il nome dell'attributo associato passato
  3. Dove non è stato assegnato alcun valore in attributeName, deve restituire -

    3.1. Per int -1 3.2. Per Datetime DateTime.MinValue 3.3. Per String, null 3.4. Per bool, null

Sotto il metodo non riesce per il caso 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)); 
     } 

Quando il cambiamento che questo

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)); 
     } 

Non riesce per tipo di stringa cioè caso 3,3

Guardando avanti per un po 'di aiuto.

+0

Come si chiama _call_ il metodo nel primo set di codice? Dovresti chiamarlo come 'AttributeValue (...)' Se chiami semplicemente 'AttributeValue (...)' allora 'null' non è un valore valido per' bool'. EDIT: E il tuo secondo caso fallisce perché 'stringa' non può essere usato per' System.Nullable 'perché' stringa' non è una struttura di tipo valore. –

risposta

4

grazie per un certo numero di risposte, questo è quello che ho scritto e funziona per me ..

Si restituisce null per i tipi.

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); 
     } 

mi chiamano in questo modo

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"); 

funziona bene per me. grazie persone ...

+0

Sto bene con ottenere valori nulli indietro ora. questa sembra una soluzione migliore, – Ashish

5

Per 3.4 è necessario utilizzare bool? come tipo per T, quindi è possibile restituire null.

Quindi è possibile utilizzare la parola chiave default per 3.3 e 3.4 (stringa e bool?). Come da msdn restituirà null per i tipi di riferimento e il valore predefinito per i tipi di valore (come int o bool).

È possibile utilizzarlo come

return default(T); 
+0

I requisiti per il caso 'bool' (3.4) sono che restituisce' null'. Ciò restituirà 'false' invece e non sarà distinguibile dal caso in cui non viene trovato alcun attributo corrispondente e il caso in cui viene fornito" false ". –

+0

Non hai bisogno di usarlo allora con 'bool?' Come argomento generico, restituendo null in quel caso? Voglio dire, se T è 'bool' non puoi restituire false, quindi devi usare' bool? '... –

+0

solo per chiarire, il valore predefinito (T) per' bool? 'Restituirà il valore nullo –

0

È necessario chiamare il primo set codice usando bool? non bool perché null non è un valore valido per un non-nullable bool.

tuo blocco secondo codice fallisce perché non è possibile utilizzare string per il tipo generico di Nullable<T> in quanto richiede un valore di tipo struct e string è una classe di riferimento di tipo.

Avrai bisogno di cambiare il vostro primo blocco del metodo per cercare typeof(bool?) e chiamarlo con un tipo booleano nullable:

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); 
} 

Quindi chiamare come:

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

È inoltre necessario fare un controllo come Convert.ChangeType non funzionerà per un tipo nullable. Una soluzione rapida da here risolve ciò.(È incluso nel codice sopra)

EDIT: Ecco una versione migliorata/pulito del metodo:

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); 
    } 
} 

È possibile aggiungere casi particolari supplementari per i nodi non-esistenti, ma tutti i casi ad eccezione di int sono già il valore predefinito per i tipi, quindi usa solo default(T).

Problemi correlati