使用反射检测属性的访问修饰符类型

22

我已经用反射写了一些代码来查看属性。我使用反射从类中检索到了属性列表。

然而,我需要找出属性是否是公共的或受保护的。例如:

public string Name{get;set;}
protected  int Age{get;set;}

PropertyInfo类似乎没有公开该属性的信息。 是否有其他方法可以实现这一点?

5个回答

29

由于属性只是对一对get/set方法的语法糖,因此在反射方面不存在属性的“可访问性”。相反,您需要分别找出getset方法的可访问级别。为此,使用GetGetMethodGetSetMethod方法检索适当的MethodInfo对象,并从那里获取各种IsPrivateIsPublic等方法和属性。


11

您需要查看每个get和set方法的methodInfo

PropertyInfo pi = ...;
bool isPublic = pi.GetGetMethod(true).IsPublic;
bool isProtected= pi.GetGetMethod(true).IsFamily;

看起来是IsFamily属性指示方法是否受保护。


9

我为此编写了一个扩展方法:

public static class ReflectionExt
{
    public static readonly List<AccessModifier> AccessModifiers = new List<AccessModifier>
    {
        AccessModifier.Private, 
        AccessModifier.Protected, 
        AccessModifier.ProtectedInternal,
        AccessModifier.Internal,  
        AccessModifier.Public
    };

    public static AccessModifier Accessmodifier(this PropertyInfo propertyInfo)
    {
        if (propertyInfo.SetMethod == null)
            return propertyInfo.GetMethod.Accessmodifier();
        if (propertyInfo.GetMethod == null)
            return propertyInfo.SetMethod.Accessmodifier();
        var max = Math.Max(AccessModifiers.IndexOf(propertyInfo.GetMethod.Accessmodifier()),
            AccessModifiers.IndexOf(propertyInfo.SetMethod.Accessmodifier()));
        return AccessModifiers[max];
    }

    public static AccessModifier Accessmodifier(this MethodInfo methodInfo)
    {
        if (methodInfo.IsPrivate)
            return AccessModifier.Private;
        if (methodInfo.IsFamily)
            return AccessModifier.Protected;
        if (methodInfo.IsFamilyOrAssembly)
            return AccessModifier.ProtectedInternal;
        if (methodInfo.IsAssembly)
            return AccessModifier.Internal;
        if (methodInfo.IsPublic)
            return AccessModifier.Public;
        throw new ArgumentException("Did not find access modifier", "methodInfo");
    }
}

public enum AccessModifier
{
    Private,
    Protected,
    Internal,
    Public
}

1
不要忘记 MethodInfo.IsFamilyOrAssembly 表示 protected internal。此外,您可以删除列表并使用枚举的序数值来计算最大值:return (AccessModifier) Math.Max((int) property.GetMethod.Accessmodifier(), (int) property.SetMethod.Accessmodifier()) - MrLore
1
@MrLore,好眼力,我已经更新了答案(你也可以做得更好)。 - T.Todua
注意新的“private protected”访问修饰符。 - Suraj

0
//.NET 6.0
namespace Test
{
    public enum AccessModifier
    {
        None,
        Private,
        Protected,
        ProtectedInternal,
        Internal,
        Public
    }

    class ReflectProperties
    {
        public class PersonInfo
        {
            public string FirstName { get; set; }
            internal string LastName { get; set; }
            protected int Age { get; set; }
            private string PhoneNumber { get; set; }
            protected internal Email {get; set; }
        }

        public static void WriteProperties()
        {
            var t = typeof(TestProperties).GetTypeInfo();

            foreach (var p in t.DeclaredProperties)
            {
                Console.WriteLine($"Property name: {p.Name}");                
                Console.WriteLine($"Accessibility: {p.GetAccessmodifier()}");
                Console.WriteLine();
            }
        }
    }    
       
    public static class MyExtensions
    {
        public static AccessModifier GetAccessmodifier(this PropertyInfo propertyInfo)
        {
            if (propertyInfo == null)
                throw new ArgumentNullException(nameof(propertyInfo));

            var setterAccessibility = propertyInfo.GetSetMethod(true)?.GetAccessmodifier() ?? AccessModifier.None;
            var getterAccessibility = propertyInfo.GetGetMethod(true)?.GetAccessmodifier() ?? AccessModifier.None;
            return Max(setterAccessibility, getterAccessibility);
        }

        private static AccessModifier Max(AccessModifier mod1, AccessModifier mod2)
        {
            if (mod1 == mod2 && mod2 == AccessModifier.None)
                throw new ArgumentException();            

            if (mod1 > mod2)
                return mod1;

            if (mod2 > mod1)
                return mod2;

            return mod1;
        }

        public static AccessModifier GetAccessmodifier(this MethodInfo methodInfo)
        {
            if (methodInfo.IsPrivate)
                return AccessModifier.Private;
            if (methodInfo.IsFamily)
                return AccessModifier.Protected;
            if (methodInfo.IsFamilyOrAssembly)
                return AccessModifier.ProtectedInternal;
            if (methodInfo.IsAssembly)
                return AccessModifier.Internal;
            if (methodInfo.IsPublic)
                return AccessModifier.Public;
            throw new ArgumentException("Did not find access modifier", "methodInfo");
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            ReflectProperties.WriteProperties();
        }
    }
}

提供关于代码的详细信息 - Pradeep Kumar
网站的规则被违反了吗? - Artem

0
    static void Main()
    {
        sample obj = new sample();
        Type t = obj.GetType();
        MethodInfo[] m = t.GetMethods();
        Console.WriteLine("Method Information:-\n\n");
        foreach (MethodInfo m1 in m)
            Console.WriteLine("Mthod name:" + m1.Name + "  \nMethod return type:" + m1.ReturnType + "\nIs staic:" + m1.IsStatic + "\nIs Public:" + m1.IsPublic + "\nIs Private:" + m1.IsPrivate);
        FieldInfo[] f = t.GetFields();
        Console.WriteLine("\n\nField Information:-\n\n");
        foreach(FieldInfo f1 in f)
            Console.WriteLine("Field name:" + f1.Name + "  \nField type:" + f1.FieldType + "\nIs staic:" + f1.IsStatic);
        Console.Read();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接