我正在对象上编写一个扩展方法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;
}
答案 0 :(得分:2)
循环浏览属性时,您将调用以下行:
((object)customType.GetValue(obj).GetType()).TrimSpaces();
调用TrimSpaces
将对象的类型作为obj
传递。相反,你应该像这样传递自己的对象:
((object)customType.GetValue(obj)).TrimSpaces();
在这种情况下,不需要转换为object
,所以你可以拥有:
customType.GetValue(obj).TrimSpaces();
答案 1 :(得分:0)
正如Yacoub指出的那样,我使用了GetValue然后调用了 TrimSpaces。就像上次我试图这样做的那样,我 得到了一个空引用异常。我写了一个空检查 开始的方法避免相同。另外,由于我的原因 我还不知道,我得到了#34; TargetParameterCountException&#34;。对于 我已经添加了一个检查我正在搜索的customType应该 不是原始类型。通过这些更改,代码似乎可以正常工作。
作为旁注,我计划修剪的对象是 复杂的深嵌套对象,具有各种用户定义的类 具有至少5级深嵌套的属性。我还没到 弄清楚为什么发生空引用异常以及 TargetParameterCountException
以下是我正在使用的最终代码。我会这样做 如果我有任何错误修复,请更新此答案
确定。我已经弄清楚问题是什么,下面是更新评论的代码。我也将保留旧代码,以便将来查看此问题的任何人都知道上下文
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; }