如何使用反射来判断一个类是否为internal?

31
正如标题所说,如何使用反射来检查类定义是否已定义为 internal?"typeof(...)"返回以下某些属性,但不包括类是否已定义为 internal。在Google上查找,但我能找到的都是关于使用反射运行内部或受保护方法的大量文章。在这种情况下,我对的不是方法,而是类定义。
var type = typeof(Customer);
Assert.IsTrue(type.IsClass);
Assert.That(type.IsAbstract, Is.EqualTo(isAbstract));
Assert.That(type.IsPublic, Is.EqualTo(isPublic));
Assert.That(type.IsPublic, Is.EqualTo(isPublic));
Assert.That(type.IsSealed, Is.EqualTo(isSealed));
Assert.That(type.IsSerializable, Is.EqualTo(isSerializable));
4个回答

38

这是一个经典问题,来自MSDN:

C#中的关键字protectedinternal在IL中没有意义,并且不会在Reflection API中使用。 IL中对应的术语是FamilyAssembly。 使用Reflection识别internal方法,请使用IsAssembly属性。 要识别protected internal方法,请使用IsFamilyOrAssembly

Reflection不能公开一种方法在Type上检查它是否是internalprotectedprotected internal


我不确定MSDN文档是否准确,但也许我错了。例如,我知道Tuple<>实现了internal interface ITuple。该接口上的Type对于上述标志为false。我自己内部类的测试表现也是如此。 - Anthony Pegram
进一步说,“嵌套”的概念就像这样 class A { class B { } },其中 B 是在 A 中嵌套的。文档中特别提到的 IsAssemblyIsFamily 属性在 Type 对象上不是公开可用的。 - Anthony Pegram
一个小修正:C#中的protected internal对应于CLR中的FamORAssem(即可见于与该程序集相同或派生类型的任何内容)。FamANDAssem在C#中没有对应项(除了在我的梦中)。 - zinglon
@zinglon:谢谢,我混淆了。 - jason
3
主要感谢@Jason的快速详细回答。感谢其他所有人提供的进一步细节。 Stack Overflow在获取答案方面确实非常出色! - Paul Hadfield
3
对于非嵌套类型,即直接属于命名空间而不包含在外部类/结构中的类型,有两个可能的级别。在反射中,它们对应于“IsPublic”和“IsNotPublic”属性。这些属性对于所有嵌套类型都返回false。对于嵌套类型,请使用诸如“IsNestedFamOrAssem”、“IsNestedPrivate”等属性(所有这些属性都以“IsNested...”开头)。 - Jeppe Stig Nielsen

13

IsVisible 方法是否能提供您所需的值?


IsVisible肯定是确定接口内部可见性的有效方法。 - Jonathan Mitchell

8
以下是一些保证正确显示类型的函数(可能是一种过度实现):
bool isPublic(Type t) {
    return
        t.IsVisible
        && t.IsPublic
        && !t.IsNotPublic
        && !t.IsNested
        && !t.IsNestedPublic
        && !t.IsNestedFamily
        && !t.IsNestedPrivate
        && !t.IsNestedAssembly
        && !t.IsNestedFamORAssem
        && !t.IsNestedFamANDAssem;
}

bool isInternal(Type t) {
    return
        !t.IsVisible
        && !t.IsPublic
        && t.IsNotPublic
        && !t.IsNested
        && !t.IsNestedPublic
        && !t.IsNestedFamily
        && !t.IsNestedPrivate
        && !t.IsNestedAssembly
        && !t.IsNestedFamORAssem
        && !t.IsNestedFamANDAssem;
}

// only nested types can be declared "protected"
bool isProtected(Type t) {
    return
        !t.IsVisible
        && !t.IsPublic
        && !t.IsNotPublic
        && t.IsNested
        && !t.IsNestedPublic
        && t.IsNestedFamily
        && !t.IsNestedPrivate
        && !t.IsNestedAssembly
        && !t.IsNestedFamORAssem
        && !t.IsNestedFamANDAssem;
}

// only nested types can be declared "private"
bool isPrivate(Type t) {
    return
        !t.IsVisible
        && !t.IsPublic
        && !t.IsNotPublic
        && t.IsNested
        && !t.IsNestedPublic
        && !t.IsNestedFamily
        && t.IsNestedPrivate
        && !t.IsNestedAssembly
        && !t.IsNestedFamORAssem
        && !t.IsNestedFamANDAssem;
}

可以定义内部嵌套类。因此,这并不适用于所有情况。 - Dimitri Troncquo

0

嗯,我不太确定,但例如

Public Function PublicFriendOrPrivate(t As Type) As String
    If t.IsPublic Then
        Return "Public"
    Else
        If t.IsNotPublic AndAlso t.IsNested Then
            Return "Private"
        Else
            Return "Friend"
        End If
    End If
End Function

注意:在C#中,“Friend”等同于“Internal”。


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