我正在尝试使用程序集的反射来获取公共字段。
程序集仅包含一个类,如下所示:
public abstract class User
{
private object _iAmPrivateField;
protected object IAmProtectedField;
internal object IAmInternalField;
public object IAmPublicField;
private void IAmPrivateMethod() { }
protected void IAmProtectedMethod() { }
internal void IAmInternalMethod() { }
public void IAmPublicMethod() { }
private object IAmPrivateProperty { get; set; }
protected object IAmProtectedProperty { get; set; }
internal object IAmInternalProperty { get; set; }
public object IAmPublicProperty { get; set; }
}
这是从给定程序集中检索公共字段的方法:
public FieldInfo[] GetPublic(Assembly assembly)
{
return assembly.GetTypes()
.SelectMany(x => x.GetFields(BindingFlags.Public | BindingFlags.Instance))
.Where(x => x.IsPublic).ToArray();
}
上面的示例按预期方式工作-结果为1。
但是我在类中添加了异步方法
public async Task IAmAsyncMethod() { }
上述更改后,GetPublic()
返回4而不是1。
是否可以过滤GetFields()
仍返回1的这些字段?
答案 0 :(得分:7)
async通过发出包含有关异步状态机信息的额外类来工作。如果使用反汇编程序(例如ILSpy)检查装配,则可以看到它。有关此概念的更多信息,请参见https://www.markopapic.com/csharp-under-the-hood-async-await/或Google“ c#异步状态机”。还为使用yield return ...
这是自动生成的异步状态机的样子,由ILSpy反编译:
[CompilerGenerated]
[Serializable]
private sealed class <>c
{
public static readonly Program.<>c <>9 = new Program.<>c();
public static Func<Type, IEnumerable<FieldInfo>> <>9__0_0;
public static Func<FieldInfo, bool> <>9__0_1;
internal IEnumerable<FieldInfo> <Main>b__0_0(Type x)
{
return x.GetFields(BindingFlags.Instance | BindingFlags.Public);
}
internal bool <Main>b__0_1(FieldInfo x)
{
return x.IsPublic;
}
}
您可以通过检查CompilerGeneratedAttribute
来省略特殊的自动生成类。将您的代码修改为:
return assembly.GetTypes()
.Where(t => t.GetCustomAttribute<CompilerGeneratedAttribute>() == null)
.SelectMany(x => x.GetFields(BindingFlags.Public | BindingFlags.Instance))
.Where(x => x.IsPublic)
.ToArray();