获取具有反射的字段

本文关键字:字段 反射的 获取 | 更新日期: 2023-09-27 17:59:45

我想获得所有具有空值的字段,但我甚至无法获得任何字段:

  [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个字段。

类型.getType().GetFields()使用错误吗?还是我把错误的类发送到基类?

获取具有反射的字段

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

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

编译器生成的与类属性相对应的字段具有CompilerGenerated属性。此外,编译器将根据属性的声明生成用于处理这些字段的getset方法。

来自编译器GeneratedAttributeMSDN文档:

区分编译器生成的元素和用户生成的元素。无法继承此类。

这些字段的名称格式为<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);
}

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

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