Получение полей по отражению асинхронно - PullRequest
0 голосов
/ 20 декабря 2018

Я пытаюсь получить открытые поля, используя отражение от сборки.

Сборка содержит только один класс, как показано ниже:

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?

1 Ответ

0 голосов
/ 20 декабря 2018

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;
    }
}

Вы можете опустить специальный autoклассы, подобные этому, проверяя на CompilerGeneratedAttribute.Изменить свой код как:

return assembly.GetTypes()
    .Where(t => t.GetCustomAttribute<CompilerGeneratedAttribute>() == null)
    .SelectMany(x => x.GetFields(BindingFlags.Public | BindingFlags.Instance))
    .Where(x => x.IsPublic)
    .ToArray();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...