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

Posted

技术标签:

【中文标题】使用反射检测属性的访问修饰符类型【英文标题】:Detect access modifier type on a property using Reflection 【发布时间】:2011-01-26 10:28:11 【问题描述】:

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

但是,我需要确定该财产是公开的还是受保护的。例如:

public string Nameget;set;
protected  int Ageget;set;

PropertyInfo 类似乎没有公开有关该属性的信息。还有其他方法吗?

【问题讨论】:

【参考方案1】:

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

【讨论】:

【参考方案2】:

需要查看每个get&set方法的methodInfo 例如:

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

这似乎是指示方法是否受保护的 IsFamily 属性..

【讨论】:

【参考方案3】:
    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();
    

【讨论】:

【参考方案4】:

为此写了一个扩展方法:

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

【讨论】:

不要忘记代表protected internalMethodInfo.IsFamilyOrAssembly。此外,您可以删除列表并使用枚举的序数值来计算最大值:return (AccessModifier) Math.Max((int) property.GetMethod.Accessmodifier(), (int) property.SetMethod.Accessmodifier()) @MrLore 很好,我已经更新了答案(你可以做得更好)。 注意新的“私人保护”访问修饰符。

以上是关于使用反射检测属性的访问修饰符类型的主要内容,如果未能解决你的问题,请参考以下文章

如果可以通过反射绕过访问修饰符,它们的目的是啥?

Java中成员属性默认访问修饰符是啥

C#关键字:访问修饰符

在运行时更改访问修饰符

Java中各种(类方法属性)访问修饰符与修饰符的说明

面向对象