Посмотрите, соответствует ли MemberInfo BindingFlags с помощью C # - PullRequest
2 голосов
/ 22 мая 2019

Мне нужно посмотреть, соответствует ли MemberInfo конкретному BindingFlags.Ближайший метод к этому - Type#GetMember(string, BindingFlags).

. Я не могу найти какой-либо способ сделать это.

Я хочу сделать что-то вроде этого:

private List<MemberInfo> _members;

public IEnumerable<MemberInfo> GetMembers(BindingFlags flags)
{
    foreach(var member in _members)
    {
        if(member.MatchesFlags(flags))
        {
             yield return member;
        }
    }
}

1 Ответ

1 голос
/ 22 мая 2019

Фактические типы MemberInfo, полученные с помощью отражения (например, посредством вызова MemberInfo[] GetMembers() на Type):

  • System.Reflection.RuntimeMethodInfo
  • System.Reflection.RuntimeConstructorInfo
  • System.Reflection.RuntimePropertyInfo
  • System.Reflection.RtFieldInfo

Все они независимо имеют свойство BindingFlags типа BindingFlags.Но собственность непубличная .И типы internal sealed, что делает их недоступными в обычном коде.Здесь reflection приходит на помощь.Чтобы получить BindingFlags из MemberInfo, можно использовать такое расширение:

public static class MemberInfoExtension
{
    private static readonly Dictionary<MemberInfo, BindingFlags> cache =
        new Dictionary<MemberInfo, BindingFlags>();
    private static readonly BindingFlags flags =
        BindingFlags.Instance | BindingFlags.NonPublic;

    public static BindingFlags GetFlags(this MemberInfo memberInfo)
    {
        if (cache.TryGetValue(memberInfo, out var bindingFlags))
            return bindingFlags;

        return cache[memberInfo] =
            (BindingFlags)memberInfo.GetType()
                                    .GetProperty("BindingFlags", flags)
                                    .GetValue(memberInfo);
    }
}

Чтобы найти совпадения с BindingFlags, можно использовать следующие вспомогательные методы:

public static class BindingFlagsExtension
{
    public static bool Contains(this BindingFlags flags, BindingFlags bindingFlags) =>
        (flags & bindingFlags) == bindingFlags;

    public static bool MatchesExactly(this BindingFlags flags, BindingFlags bindingFlags) =>
        flags == bindingFlags;

    public static bool MatchesPartly(this BindingFlags flags, BindingFlags bindingFlags) =>
        (flags & bindingFlags) != 0;
}

Чтобы проверить решение, можно использовать такой класс:

private class DemoClass
{
    private int PrivateInstanceField;
    public string PublicInstanceField;
    private bool PrivateInstanceProperty { get; }
    public object PublicInstanceProperty { get; }
    private void PrivateInstanceMethod() { }
    public void PublicInstanceMethod() { }
    private static int PrivateStaticField;
    public static string PublicStaticField;
    private static bool PrivateStaticProperty { get; }
    public static object PublicStaticProperty { get; }
    private static void PrivateStaticMethod() { }
    public static void PublicStaticMethod() { }
}

Затем запустить:

static void Main(string[] args)
{
    var type = typeof(DemoClass);
    var members = type.GetMembers();
    var flags = BindingFlags.Public | BindingFlags.Instance;

    Console.WriteLine($"{type.Name} members with flags containing: {flags}\n");
    foreach (var m in members.Where(m => m.GetFlags().Contains(flags)))
        Print(m);

    Console.WriteLine($"\n{type.Name} members with flags matching exactly: {flags}\n");
    foreach (var m in members.Where(m => m.GetFlags().MatchesExactly(flags)))
        Print(m);

    Console.WriteLine($"\n{type.Name} members with flags matching partly: {flags}\n");
    foreach (var m in members.Where(m => m.GetFlags().MatchesPartly(flags)))
        Print(m);
}

private static void Print(MemberInfo memberInfo) =>
    Console.WriteLine($"\t{memberInfo.GetType().Name} {memberInfo} - {memberInfo.GetFlags()}");

дает:

DemoClass members with flags containing: Instance, Public

        RuntimeMethodInfo System.Object get_PublicInstanceProperty() - Instance, Public
        RuntimeMethodInfo Void PublicInstanceMethod() - Instance, Public
        RuntimeMethodInfo Boolean Equals(System.Object) - DeclaredOnly, Instance, Public
        RuntimeMethodInfo Int32 GetHashCode() - DeclaredOnly, Instance, Public
        RuntimeMethodInfo System.Type GetType() - DeclaredOnly, Instance, Public
        RuntimeMethodInfo System.String ToString() - DeclaredOnly, Instance, Public
        RuntimeConstructorInfo Void .ctor() - Instance, Public
        RuntimePropertyInfo System.Object PublicInstanceProperty - Instance, Public
        RtFieldInfo System.String PublicInstanceField - Instance, Public

DemoClass members with flags matching exactly: Instance, Public

        RuntimeMethodInfo System.Object get_PublicInstanceProperty() - Instance, Public
        RuntimeMethodInfo Void PublicInstanceMethod() - Instance, Public
        RuntimeConstructorInfo Void .ctor() - Instance, Public
        RuntimePropertyInfo System.Object PublicInstanceProperty - Instance, Public
        RtFieldInfo System.String PublicInstanceField - Instance, Public

DemoClass members with flags matching partly: Instance, Public

        RuntimeMethodInfo System.Object get_PublicInstanceProperty() - Instance, Public
        RuntimeMethodInfo Void PublicInstanceMethod() - Instance, Public
        RuntimeMethodInfo System.Object get_PublicStaticProperty() - Static, Public
        RuntimeMethodInfo Void PublicStaticMethod() - Static, Public
        RuntimeMethodInfo Boolean Equals(System.Object) - DeclaredOnly, Instance, Public
        RuntimeMethodInfo Int32 GetHashCode() - DeclaredOnly, Instance, Public
        RuntimeMethodInfo System.Type GetType() - DeclaredOnly, Instance, Public
        RuntimeMethodInfo System.String ToString() - DeclaredOnly, Instance, Public
        RuntimeConstructorInfo Void .ctor() - Instance, Public
        RuntimePropertyInfo System.Object PublicInstanceProperty - Instance, Public
        RuntimePropertyInfo System.Object PublicStaticProperty - Static, Public
        RtFieldInfo System.String PublicInstanceField - Instance, Public
        RtFieldInfo System.String PublicStaticField - Static, Public
...