用反射清理我的代码

时间:2011-06-17 13:52:28

标签: c# serialization reflection

我想用反射遍历我的Car类来删除所有空值并用更好的值替换它们,比如string =“”。

    [Serializable()]
public class Car
{
    public string model;
    public int year;
    public List<Owner> owner;
}

[Serializable()]
public class Owner
{
    public string firstName;
    public string lastName;
}

到目前为止,我已经做到了这一点

   public void LoopEverythingAndFix(object type)
    {
        var prop = type.GetType().GetFields();

        foreach (var fieldInfo in prop)
        {
            if (GetType(fieldInfo))
            {
                var value = fieldInfo.GetValue(type);

                if (value == null)
                    fieldInfo.SetValue(type, GetDefaultValue(fieldInfo));
            }
            else
            {
                LoopEverythingAndFix(fieldInfo);
            }
        }
    }
    public bool GetType(System.Reflection.FieldInfo fieldInfo)
    {
        if (fieldInfo.FieldType == typeof(string))
            return true;

        if (fieldInfo.FieldType == typeof(bool))
            return true;

        if (fieldInfo.FieldType == typeof(int))
            return true;

        if (fieldInfo.FieldType == typeof(decimal))
            return true;

        return false;
    }

GetType方法是知道当前字段是否类似于“所有者”类,或者它的值/引用字段是否类似于int / string,如果它是“所有者”类型,那么我想要将它循环到并修复这些属性。

问题在于它在汽车类中找到“所有者”,然后执行:

 LoopEverythingAndFix(fieldInfo);

问题所在,因为我将fieldInfo发送给方法LoopEverythingAndFix,当它返回循环时,它会在type.GetType().GetFields()获得0个字段。这是一个列表,我想循环列表项并将它们发送到LoopEverythingAndFix方法

3 个答案:

答案 0 :(得分:3)

您尝试在反射类型LoopEverythingAndFix上调用FieldInfo,而不是要修复的实际对象。

要解决此问题,请将其替换为:

LoopEverythingAndFix(fieldInfo);

有了这个:

LoopEverythingAndFix(fieldInfo.GetValue(type));

答案 1 :(得分:0)

似乎问题在于,您传递的是对静态类所有者的引用,而不是传递一个Owner对象。所以你已经拥有了所有者的类型。

答案 2 :(得分:0)

您的代码存在一些问题需要解决:

  1. 您正在对已知值类型执行空检查。除Nullable<T>之外的ValueType实例永远不会为null。此操作是不必要的,会影响性能。我在下面解决了这个问题。

  2. 您没有考虑string以外的空引用类型字段的情况。例如,如果存在空Owner或空List<Owner>,会发生什么?

  3. 由于您没有发布GetDefaultValue()函数,因此它的签名有点不清楚。我的猜测是它接受FieldInfo并根据字段类型解析默认的非空值。因为,实际上这仅适用于string参数,最好用string.Empty替换呼叫。我在下面的评论中指出了这一点。

  4. 下面,我在下面对您的功能进行了整合,优化和重写,并附有注释以指示必须更改或插入不同行为的位置。

    public void LoopEverythingAndFix(object instance)
    {
        var fields = instance.GetType().GetFields(BindingFlags.Public|BindingFlags.Instance)
        foreach(var fieldInfo in fields){
           var fieldType = fieldInfo.FieldType;
           if(!fieldType.IsValueType){
              bool isString = fieldType == typeof(string);
              var fieldValue = fieldInfo.GetValue(instance);
              if(fieldValue != null){
                    if(!isString){
                        // This should recursion be called when the type is a 
                        // complex (non-string) reference type that is not null
                        LoopEverythingAndFix(fieldValue);
                    }
                    // You don't need to fix a non-null string value
              }
              else{
                  if(isString){
                      // since you didn't post the code for this, I am assuming 
                      // it works correctly, but it may be that you can just replace
                      // GetDefaultValue(fieldInfo) with string.Empty 
                      fieldInfo.SetValue(instance, GetDefaultValue(fieldInfo));
                  }
                  else{
                      // It is unclear how you want to handle a complex reference type 
                      // field with a null value.  That code should go here.
                  }
              }
           } 
        }
    }