1

我需要使用反射获取代表对象确切状态的所有成员。所以这些成员包括字段 ( FieldInfo) 和自动属性 ​​( PropertyInfo)。我可以得到所有的FieldInfos 使用

type.GetFields(); //ok some flags needed here

并获取此链接中提到的自动实现的属性:

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....) ?
4

2 回答 2

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
于 2013-05-12T06:59:35.460 回答
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

有点骇人听闻,但这给出了字段和自动属性(不像杰里米的答案只给出字段信息)。

于 2013-05-12T14:09:57.907 回答