我需要使用反射来获取代表对象的精确状态的所有成员。因此,这些成员包括字段(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....) ?
答案 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的回答只给出了字段信息)。