2013-06-28 28 views
6

tôi viết dưới đây phương pháp với follwing yêu cầu -phương pháp Generic trở Nullable Loại giá trị

  1. đầu vào là XmlNode và AttributeName
  2. trở lại giá trị nếu nó được tìm thấy với tên thuộc tính liên quan đến thông qua
  3. Trường hợp không có giá trị trong attributeName được chuyển, nó sẽ trả về -

    3.1. Đối với int -1 3.2. Đối với ngày giờ DateTime.MinValue 3.3. Đối với chuỗi, null 3.4. Đối với bool, null

Phương pháp dưới đây không thành công cho trường hợp 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)); 
     } 

Khi thay đổi này để

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

Nó không cho loại chuỗi ví dụ: trường hợp 3,3

Mong cho một số giúp đỡ.

+0

Làm thế nào để bạn _call_ phương pháp trong bộ mã đầu tiên của bạn? Bạn cần gọi nó là 'AttributeValue (...) 'Nếu bạn chỉ cần gọi' AttributeValue (...) 'thì' null' không phải là giá trị hợp lệ cho 'bool'. EDIT: Và trường hợp thứ hai của bạn thất bại vì 'string' không thể được sử dụng cho' System.Nullable 'vì' string' không phải là một struct kiểu giá trị. –

Trả lời

4

cảm ơn một số câu trả lời, đây là những gì tôi đã viết và nó hoạt động cho tôi ..

Nó trả về null cho các loại.

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

tôi gọi nó như thế này

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

nó hoạt động tốt đối với tôi. cảm ơn mọi người ...

+0

Tôi ổn với giá trị null trở lại ngay bây giờ. điều này trông giống như một giải pháp tốt hơn, – Ashish

5

Đối với 3.4, bạn cần sử dụng bool? làm loại cho T, vì vậy bạn có thể trả về giá trị rỗng.

Sau đó, bạn có thể sử dụng từ khóa default cho 3,3 và 3,4 (chuỗi và bool?). Theo msdn, nó sẽ trả lại null cho các loại tham chiếu và giá trị mặc định cho các loại giá trị (như int hoặc bool).

Bạn có thể sử dụng nó như

return default(T); 
+0

Các yêu cầu đối với trường hợp 'bool' (3.4) là nó trả về' null'. Điều này sẽ trả về 'false' thay vào đó và sẽ không thể phân biệt được với trường hợp không tìm thấy thuộc tính phù hợp và trường hợp" false "được cung cấp. –

+0

Bạn không cần sử dụng nó với 'bool? 'Làm đối số chung, trả về null trong trường hợp đó? Ý tôi là, nếu T là 'bool' bạn không thể trả về false, vì vậy bạn cần sử dụng' bool? '... –

+0

chỉ để làm rõ, mặc định (T) cho' bool? 'Sẽ trả về null –

0

Bạn cần phải gọi bộ mã đầu tiên bạn sử dụng bool? không boolnull không phải là một giá trị hợp lệ cho một tổ chức phi nullable bool.

khối mã thứ hai của bạn không thành công vì bạn không thể sử dụng string cho các loại hình chung của Nullable<T> vì nó đòi hỏi một giá trị kiểu structstring là một lớp học tham khảo kiểu.

Bạn sẽ cần phải thay đổi khối phương pháp đầu tiên của bạn để tìm kiếm typeof(bool?) và gọi nó với một kiểu boolean 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); 
} 

Sau đó gọi nó là:

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

Bạn cũng cần phải làm một kiểm tra như Convert.ChangeType sẽ không hoạt động cho một loại nullable. Sửa nhanh từ here giải quyết vấn đề đó.(Nó được bao gồm trong các mã trên)

EDIT: Dưới đây là một phiên bản cải tiến/làm sạch của phương pháp của bạn:

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

Bạn có thể bổ sung thêm trường hợp đặc biệt cho các nút không tồn tại, nhưng tất cả các trường hợp của bạn ngoại trừ int đã là giá trị mặc định cho các loại, do đó, chỉ cần sử dụng default(T) thay thế.