2016-02-05 52 views
2

我在對象上編寫了一個擴展方法TrimSpaces,以便它遞歸地應該能夠修剪空格。我成功修剪了第一級對象的空間,但是,我無法對子對象執行相同的操作。使用反射遞歸地修剪對象中的空間

作爲一個例子,考慮下面的類

public class Employee 
{ 
    public string EmployeeID { get; set; } 
    public string EmployeeName { get; set; } 
    public DateTime HireDate { get; set; } 
    public Department EmployeeDepartment { get; set; } 
} 

public class Department 
{ 
    public int DepartmentID { get; set; } 
    public string DepartmentName { get; set; } 
} 

在上面的類我目前能夠從Employee類的屬性微調空間,但我無法修剪DepartmentName的

下面是代碼我寫

public static T TrimSpaces<T>(this T obj) 
    { 
     var properties = obj.GetType() 
      .GetProperties(BindingFlags.Instance | BindingFlags.Public) 
      .Where(prop => prop.PropertyType == typeof(string)) 
      .Where(prop => prop.CanWrite && prop.CanRead); 
     foreach (var property in properties) 
     { 
      var value = (string)property.GetValue(obj, null); 
      if (value.HasValue()) 
      { 
       var newValue = (object)value.Trim(); 
       property.SetValue(obj, newValue, null); 
      } 
     } 


     var customTypes = 
      obj.GetType() 
       .GetProperties(BindingFlags.Instance | BindingFlags.Public) 
       .Where(
        prop => 
         !prop.GetType().IsPrimitive && prop.GetType().IsClass && 
         !prop.PropertyType.FullName.StartsWith("System")); 

     foreach (var customType in customTypes) 
     { 
      ((object)customType.GetValue(obj).GetType()).TrimSpaces(); 
     } 

     return obj; 
    } 
+1

你不是應該叫'((對象) customType.GetValue(obj))。TrimSpaces();',即沒有'.GetType()'? –

回答

2

當您通過性循環,你正在調用該行:

((object)customType.GetValue(obj).GetType()).TrimSpaces(); 

哪個調用TrimSpaces將對象的類型傳遞爲obj。相反,你應該傳遞對象它的自我是這樣的:

((object)customType.GetValue(obj)).TrimSpaces(); 

在這種情況下,不需要強制轉換爲object,這樣你就可以有這樣的:

customType.GetValue(obj).TrimSpaces(); 
0

至於雅各布指出,我使用了GetValue,然後調用了 TrimSpaces。就像我上次試圖這樣做,我 得到一個空引用異常。我已經在該方法的開頭 處寫了一個空檢查以避免相同。另外,由於我還不知道的原因,我得到了「TargetParameterCountException」。對於 ,我已經添加了一個檢查到customType我正在尋找應 不是一個原始類型。隨着這些變化,代碼似乎工作。

作爲邊注,在其上我打算做修整的對象是與各種用戶定義的類如 屬性與至少5級深度嵌套 複雜深度嵌套對象。我仍然沒有 搞清楚爲什麼空引用異常發生,也是 TargetParameterCountException

下面是我使用的是做工作。我會 更新這個答案,如果我有任何的bug最終代碼修復程序

好的。我已經找出了問題所在,下面是更新了評論的代碼。我也離開舊代碼,以便任何人檢查將來這個問題會知道上下文

public static T TrimSpaces<T>(this T obj) 
    { 
     if (obj == null) 
     { 
      return obj; 
     } 

     //Iterates all properties and trims the values if they are strings 
     var properties = obj.GetType() 
      .GetProperties(BindingFlags.Instance | BindingFlags.Public) 
      .Where(prop => prop.PropertyType == typeof(string)) 
      .Where(prop => prop.CanWrite && prop.CanRead); 

     foreach (var property in properties) 
     { 
      var value = (string)property.GetValue(obj, null); 
      if (value.HasValue()) 
      { 
       var newValue = (object)value.Trim(); 
       property.SetValue(obj, newValue, null); 
      } 
     } 


     // This is to take care of Lists. This iterates through each value 
     // in the list. 
     // For example, Countries which is a List<Country> 
     var baseTypeInfo = obj.GetType().BaseType; 
     if (baseTypeInfo != null && baseTypeInfo.FullName.Contains("List")) 
     { 
      int listCount = (int)obj.GetType().GetProperty("Count").GetValue(obj, null); 
      for (int innerIndex = 0; innerIndex < listCount; innerIndex++) 
      { 
       object item = obj.GetType() 
        .GetMethod("get_Item", new Type[] { typeof(int) }) 
        .Invoke(obj, new object[] { innerIndex }); 
       item.TrimSpaces(); 
      } 
     } 


     // Now once we are in a complex type (for example Country) it then needs to 
     // be trimmed recursively using the initial peice of code of this method 
     // Hence if it is a complex type we are recursively calling TrimSpaces 
     var customTypes = 
      obj.GetType() 
       .GetProperties(BindingFlags.Instance | BindingFlags.Public) 
       .Where(
        prop => 
         !prop.GetType().IsPrimitive && prop.GetType().IsClass && 
         !prop.PropertyType.FullName.StartsWith("System")); 

     foreach (var customType in customTypes) 
     { 
      // If it's a collection, let the about piece of code take care 
      // Only, normal types like, Code etc will be trimmed 
      if (customType.GetIndexParameters().Length == 0) 
      { 
       customType.GetValue(obj).TrimSpaces(); 
      } 
     } 

     return obj; 
    } 

舊代碼:

public static T TrimSpaces<T>(this T obj) 
    { 

     if (obj == null) 
     { 
      return obj; 
     } 

     var properties = obj.GetType() 
      .GetProperties(BindingFlags.Instance | BindingFlags.Public) 
      .Where(prop => prop.PropertyType == typeof(string)) 
      .Where(prop => prop.CanWrite && prop.CanRead); 
     foreach (var property in properties) 
     { 
      var value = (string)property.GetValue(obj, null); 
      if (value.HasValue()) 
      { 
       var newValue = (object)value.Trim(); 
       property.SetValue(obj, newValue, null); 
      } 
     } 


     var customTypes = 
      obj.GetType() 
       .GetProperties(BindingFlags.Instance | BindingFlags.Public) 
       .Where(
        prop => 
         !prop.GetType().IsPrimitive && prop.GetType().IsClass && 
         !prop.PropertyType.FullName.StartsWith("System")); 

     foreach (var customType in customTypes) 
     { 
      if (customType.Name.Contains("Item")) 
      { 
       continue; 
      } 

      customType.GetValue(obj).TrimSpaces(); 
     } 

     return obj; 
    }