【问题标题】:get fields with reflection [duplicate]获取具有反射的字段[重复]
【发布时间】:2011-06-18 08:51:16
【问题描述】:

我想获取所有具有空值的字段,但我什至没有获取任何字段:

  [Serializable()]
public class BaseClass
{
    [OnDeserialized()]
    internal void OnDeserializedMethod(StreamingContext context)
    {
        FixNullString(this);
    }

    public void FixNullString(object type)
    {
        try
        {
            var properties = type.GetType().GetFields();


            foreach (var property in from property in properties
                                     let oldValue = property.GetValue(type)
                                     where oldValue == null
                                     select property)
            {
                property.SetValue(type, GetDefaultValue(property));
            }
        }
        catch (Exception)
        {

        }
    }

    public object GetDefaultValue(System.Reflection.FieldInfo value)
    {
        try
        {
            if (value.FieldType == typeof(string))
                return "";

            if (value.FieldType == typeof(bool))
                return false;

            if (value.FieldType == typeof(int))
                return 0;

            if (value.FieldType == typeof(decimal))
                return 0;

            if (value.FieldType == typeof(DateTime))
                return new DateTime();
        }
        catch (Exception)
        {

        }

        return null;
    }
}

然后我有一节课:

    [Serializable()]
public class Settings : BaseClass
{
    public bool Value1 { get; set; }
    public bool Value2 { get; set; }
}

但是当我谈到

 var properties = type.GetType().GetFields();

然后我得到 0 个字段,它应该找到 2 个字段。

type.getType().GetFields() 用错了吗?还是我将错误的类发送到基类?

【问题讨论】:

    标签: c# class reflection


    【解决方案1】:

    Type.GetFields 方法返回所有公共字段。编译器为您自动生成的字段是私有的,因此您需要指定正确的BindingFlags

    type.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
    

    【讨论】:

      【解决方案2】:

      编译器生成的对应于类属性的字段具有CompilerGenerated 属性。此外,编译器将生成 getset 方法来处理这些字段,具体取决于您的属性声明。

      来自 CompilerGeneratedAttribute MSDN 文档:

      区分编译器生成的元素和用户生成的元素。这个类不能被继承。

      这些字段的名称格式为<PropertyName>k_BackingField,方法setget 名称格式为set_PropertyNameget_PropertyName,其中PropertyName 是属性名称。

      比如你的Settings类编译如下:

      [Serializable]
      public class Settings : BaseClass
      {
          public Settings(){}
      
          // Properties
          [CompilerGenerated]
          private bool <Value1>k__BackingField;
      
          [CompilerGenerated]
          private bool <Value2>k__BackingField;
      
          [CompilerGenerated]
          public void set_Value1(bool value)
          {
              this.<Value1>k__BackingField = value;
          }
      
          [CompilerGenerated]
          public bool get_Value1()
          {
              return this.<Value1>k__BackingField;
          } 
      
          [CompilerGenerated]
          public void set_Value2(bool value)
          {
              this.<Value2>k__BackingField = value;
          }
      
          [CompilerGenerated]
          public bool get_Value2()
          {
              return this.<Value2>k__BackingField;
          }
      }
      

      如果您希望排除此支持字段,您可以使用此方法:

      public IEnumerable<FieldInfo> GetFields(Type type)
      {
          return type
              .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
              .Where(f => f.GetCustomAttribute<CompilerGeneratedAttribute>() == null);
      }
      

      【讨论】:

        【解决方案3】:

        Settings 类中的Value1Value2 是属性而不是字段,因此您需要使用GetProperties() 来访问它们。

        (使用{ get; set; } 语法告诉编译器您需要一个属性,但它应该为您生成getset,以及一个包含数据的隐藏私有字段。)

        【讨论】:

          猜你喜欢
          • 2021-08-08
          • 1970-01-01
          • 1970-01-01
          • 2013-02-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-08
          相关资源
          最近更新 更多