获取反映对象状态的所有MemberInfos的最简单方法是什么?

时间:2013-05-12 05:47:37

标签: c# reflection automatic-properties fieldinfo

我需要使用反射来获取代表对象的精确状态的所有成员。因此,这些成员包括字段(FieldInfo)和自动属性(PropertyInfo)。我可以使用

获取所有FieldInfo
type.GetFields(); //ok some flags needed here

获取此link中提到的自动实现的属性:

public static bool MightBeCouldBeMaybeAutoGeneratedInstanceProperty(this PropertyInfo info)
{
    bool mightBe = info.GetGetMethod().HasCompilerGeneratedAttribute();
    if (!mightBe)
        return false;

    bool maybe = info.DeclaringType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
                                   .Where(f => f.Name.Contains(info.Name))
                                   .Where(f => f.Name.Contains("BackingField"))
                                   .Where(f => f.HasCompilerGeneratedAttribute())
                                   .Any();

    return maybe;
}

public static bool HasCompilerGeneratedAttribute(this MemberInfo mi)
{
    return mi.GetCustomAttributes(typeof(CompilerGeneratedAttribute), true).Any();
}

正如回答者所说,这确实很脆弱。是否有更多的标准方法来实现这一目标?我在想,可能是BindingFlags左右的东西?

type.GetMembers(BindingFlags....) ?

2 个答案:

答案 0 :(得分:2)

如果通过“对象的确切状态”你只是意味着它包含的所有实例字段(如果没有,你能澄清吗?),那么你应该能够用一个语句来做 - 没有显着差别您明确声明的字段,以及编译器为您添加的自动属性的后备字段。如果您定义一个类:

public class FieldInfoTest
{
  private string testField;

  public string TestProperty { get; set; }
}

...你可以一下子访问它们

FieldInfo[] fields = typeof(FieldInfoTest).GetFields(BindingFlags.Instance |
                                                     BindingFlags.Public | 
                                                     BindingFlags.NonPublic);

foreach (var f in fields)
{
  Console.WriteLine(f.Name);
}

这将产生:

testField
<TestProperty>k__BackingField

答案 1 :(得分:0)

杰里米的答案是我能得到的最好的答案。这是另一种选择(我最初提到的问题):

public static IEnumerable<MemberInfo> GetStateMembers(this Type t)
{
    return t.GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
            .Where(m => m.MemberType == MemberTypes.Field && !((FieldInfo)m).Name.Contains('<')
                     || m.MemberType == MemberTypes.Property && ((PropertyInfo)m).IsAutoProperty());
}

public static bool IsAutoProperty(this PropertyInfo prop)
{
    if (!prop.CanWrite || !prop.CanRead)
        return false;

    return prop.DeclaringType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
                             .Any(f => f.Name.Contains("<" + prop.Name + ">"));
}

有关其如何运作的更多说明:https://stackoverflow.com/a/16506710/661933

有点hackish,但这给了字段和自动属性(不像Jeremy的回答只给出了字段信息)。