`
RednaxelaFX
  • 浏览: 3017525 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

类型的可见性,System.Reflection与Mono.Cecil的差异

    博客分类:
  • C#
阅读更多
C#的访问限制修饰符对应到Type的可见性属性有以下对应关系:

顶层类:
public -> IsPublic
internal -> IsNotPublic
(默认)-> internal -> IsNotPublic
嵌套类:
public -> IsNestedPublic
protected -> IsNestedFamily
protected internal -> IsNestedFamilyOrAssembly
private -> IsNestedPrivate
(默认)-> private -> IsNestedPrivate

注意:这些属性之中总是有且只有一个属性为真。一个嵌套类的Type只会显示自身的可见性,其外围类的可见性需要通过Type.DeclaringType找到其外围类的Type来查询。
C#无法表示IsFamANDAssem可见性的类型。

用一段代码通过System.Reflection来测试一下上述对应关系:

using System;
using System.Reflection;

namespace TestReflection {
    static class Program {
        static void Main( string[ ] args ) {
            var asm = Assembly.GetExecutingAssembly( );
            foreach ( var type in asm.GetTypes( ) ) {
                PrintTypeInfo( type );
            }
        }

        static void PrintTypeInfo( Type type ) {
            Console.WriteLine( "Type: {0}", type.ToString( ) );
            Console.WriteLine( "  Name: {0}", type.Name );
            Console.WriteLine( "  FullName: {0}", type.FullName ?? "null" );

            // type of type
            Console.WriteLine( "  IsClass = {0}", type.IsClass );
            Console.WriteLine( "  IsInterface = {0}", type.IsInterface );
            Console.WriteLine( "  IsEnum = {0}", type.IsEnum );
            Console.WriteLine( "  IsValueType = {0}", type.IsValueType );

            // access modifiers
            Console.WriteLine( "  IsPublic = {0}", type.IsPublic );
            Console.WriteLine( "  IsNotPublic = {0}", type.IsNotPublic );
            Console.WriteLine( "  IsNested = {0}", type.IsNested );
            Console.WriteLine( "  IsNestedAssembly = {0}", type.IsNestedAssembly );
            Console.WriteLine( "  IsNestedFamily = {0}", type.IsNestedFamily );
            Console.WriteLine( "  IsNestedFamilyAndAssembly = {0}", type.IsNestedFamANDAssem );
            Console.WriteLine( "  IsNestedFamilyOrAssembly = {0}", type.IsNestedFamORAssem );
            Console.WriteLine( "  IsNestedPrivate = {0}", type.IsNestedPrivate );
            Console.WriteLine( "  IsNestedPublic = {0}", type.IsNestedPublic );

            Console.WriteLine( );
        }
    }

    public class PublicClass {
        public class PublicInnerPublicClass { }
        internal class InternalInnerPublicClass { }
        protected class ProtectedInnerPublicClass { }
        protected internal class ProtectedInternalInnerPublicClass { }
        private class PrivateInnerPublicClass { }
        class DefaultInnerPublicClass { }
    }

    /*internal*/
    class InternalClass {
        public class PublicInnerInternalClass { }
        internal class InternalInnerInternalClass { }
        protected class ProtectedInnerInternalClass { }
        protected internal class ProtectedInternalInnerInternalClass { }
        private class PrivateInnerInternalClass { }
        class DefaultInnerInternalClass { }
    }

    enum InternalEnum { A }
    struct InternalStruct { }
}


运行结果:
引用
Type: TestReflection.Program
  Name: Program
  FullName: TestReflection.Program
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = True
  IsNested = False
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestReflection.PublicClass
  Name: PublicClass
  FullName: TestReflection.PublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = True
  IsNotPublic = False
  IsNested = False
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestReflection.PublicClass+PublicInnerPublicClass
  Name: PublicInnerPublicClass
  FullName: TestReflection.PublicClass+PublicInnerPublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = True

Type: TestReflection.PublicClass+InternalInnerPublicClass
  Name: InternalInnerPublicClass
  FullName: TestReflection.PublicClass+InternalInnerPublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = True
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestReflection.PublicClass+ProtectedInnerPublicClass
  Name: ProtectedInnerPublicClass
  FullName: TestReflection.PublicClass+ProtectedInnerPublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = True
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestReflection.PublicClass+ProtectedInternalInnerPublicClass
  Name: ProtectedInternalInnerPublicClass
  FullName: TestReflection.PublicClass+ProtectedInternalInnerPublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = True
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestReflection.PublicClass+PrivateInnerPublicClass
  Name: PrivateInnerPublicClass
  FullName: TestReflection.PublicClass+PrivateInnerPublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = True
  IsNestedPublic = False

Type: TestReflection.PublicClass+DefaultInnerPublicClass
  Name: DefaultInnerPublicClass
  FullName: TestReflection.PublicClass+DefaultInnerPublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = True
  IsNestedPublic = False

Type: TestReflection.InternalClass
  Name: InternalClass
  FullName: TestReflection.InternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = True
  IsNested = False
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestReflection.InternalClass+PublicInnerInternalClass
  Name: PublicInnerInternalClass
  FullName: TestReflection.InternalClass+PublicInnerInternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = True

Type: TestReflection.InternalClass+InternalInnerInternalClass
  Name: InternalInnerInternalClass
  FullName: TestReflection.InternalClass+InternalInnerInternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = True
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestReflection.InternalClass+ProtectedInnerInternalClass
  Name: ProtectedInnerInternalClass
  FullName: TestReflection.InternalClass+ProtectedInnerInternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = True
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestReflection.InternalClass+ProtectedInternalInnerInternalClass
  Name: ProtectedInternalInnerInternalClass
  FullName: TestReflection.InternalClass+ProtectedInternalInnerInternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = True
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestReflection.InternalClass+PrivateInnerInternalClass
  Name: PrivateInnerInternalClass
  FullName: TestReflection.InternalClass+PrivateInnerInternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = True
  IsNestedPublic = False

Type: TestReflection.InternalClass+DefaultInnerInternalClass
  Name: DefaultInnerInternalClass
  FullName: TestReflection.InternalClass+DefaultInnerInternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = True
  IsNestedPublic = False

Type: TestReflection.InternalEnum
  Name: InternalEnum
  FullName: TestReflection.InternalEnum
  IsClass = False
  IsInterface = False
  IsEnum = True
  IsValueType = True
  IsPublic = False
  IsNotPublic = True
  IsNested = False
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestReflection.InternalStruct
  Name: InternalStruct
  FullName: TestReflection.InternalStruct
  IsClass = False
  IsInterface = False
  IsEnum = False
  IsValueType = True
  IsPublic = False
  IsNotPublic = True
  IsNested = False
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

注意到嵌套类的全名中的'+',那是外围类的全名与嵌套类的类名连接的地方。

===========================================================================

用System.Reflection来加载assembly有一个缺点,那就是加载了的assembly在程序结束前无法卸载,会一直占用内存。为了绕开这个问题,可以用Mono.Cecil来加载assembly并获取相关类型信息。

下面是用SVN trunk里的Mono.Cecil来做同样的测试:

using System;
using System.Reflection;
using Mono.Cecil;

namespace TestCecil {
    static class Program {
        static void Main( string[ ] args ) {
            var path = Assembly.GetExecutingAssembly( ).Location;
            AssemblyDefinition asm = AssemblyFactory.GetAssembly( path );
            ModuleDefinition module = asm.MainModule;
            foreach ( TypeDefinition type in module.Types ) {
                PrintTypeInfo( type );
            }
        }

        static void PrintTypeInfo( TypeDefinition type ) {
            Console.WriteLine( "Type: {0}", type.ToString( ) );
            Console.WriteLine( "  Name: {0}", type.Name );
            Console.WriteLine( "  FullName: {0}", type.FullName ?? "null" );

            // type of type
            Console.WriteLine( "  IsClass = {0}", type.IsClass );
            Console.WriteLine( "  IsInterface = {0}", type.IsInterface );
            Console.WriteLine( "  IsEnum = {0}", type.IsEnum );
            Console.WriteLine( "  IsValueType = {0}", type.IsValueType );

            // access modifiers
            Console.WriteLine( "  IsPublic = {0}", type.IsPublic );
            Console.WriteLine( "  IsNotPublic = {0}", type.IsNotPublic );
            Console.WriteLine( "  IsNested = {0}", type.IsNested );
            Console.WriteLine( "  IsNestedAssembly = {0}", type.IsNestedAssembly );
            Console.WriteLine( "  IsNestedFamily = {0}", type.IsNestedFamily );
            Console.WriteLine( "  IsNestedFamilyAndAssembly = {0}", type.IsNestedFamilyAndAssembly );
            Console.WriteLine( "  IsNestedFamilyOrAssembly = {0}", type.IsNestedFamilyOrAssembly );
            Console.WriteLine( "  IsNestedPrivate = {0}", type.IsNestedPrivate );
            Console.WriteLine( "  IsNestedPublic = {0}", type.IsNestedPublic );

            Console.WriteLine( );
        }
    }

    public class PublicClass {
        public class PublicInnerPublicClass { }
        internal class InternalInnerPublicClass { }
        protected class ProtectedInnerPublicClass { }
        protected internal class ProtectedInternalInnerPublicClass { }
        private class PrivateInnerPublicClass { }
        class DefaultInnerPublicClass { }
    }

    /*internal*/
    class InternalClass {
        public class PublicInnerInternalClass { }
        internal class InternalInnerInternalClass { }
        protected class ProtectedInnerInternalClass { }
        protected internal class ProtectedInternalInnerInternalClass { }
        private class PrivateInnerInternalClass { }
        class DefaultInnerInternalClass { }
    }

    enum InternalEnum { A }
    struct InternalStruct { }
}


运行结果:
引用
Type: <Module>
  Name: <Module>
  FullName: <Module>
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = True
  IsNested = False
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False


Type: TestCecil.Program
  Name: Program
  FullName: TestCecil.Program
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = True
  IsNested = False
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestCecil.PublicClass
  Name: PublicClass
  FullName: TestCecil.PublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = True
  IsNotPublic = False
  IsNested = False
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestCecil.PublicClass/PublicInnerPublicClass
  Name: PublicInnerPublicClass
  FullName: TestCecil.PublicClass/PublicInnerPublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = True

Type: TestCecil.PublicClass/InternalInnerPublicClass
  Name: InternalInnerPublicClass
  FullName: TestCecil.PublicClass/InternalInnerPublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = True
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestCecil.PublicClass/ProtectedInnerPublicClass
  Name: ProtectedInnerPublicClass
  FullName: TestCecil.PublicClass/ProtectedInnerPublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = True
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestCecil.PublicClass/ProtectedInternalInnerPublicClass
  Name: ProtectedInternalInnerPublicClass
  FullName: TestCecil.PublicClass/ProtectedInternalInnerPublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = True
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestCecil.PublicClass/PrivateInnerPublicClass
  Name: PrivateInnerPublicClass
  FullName: TestCecil.PublicClass/PrivateInnerPublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = True
  IsNestedPublic = False

Type: TestCecil.PublicClass/DefaultInnerPublicClass
  Name: DefaultInnerPublicClass
  FullName: TestCecil.PublicClass/DefaultInnerPublicClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = True
  IsNestedPublic = False

Type: TestCecil.InternalClass
  Name: InternalClass
  FullName: TestCecil.InternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = True
  IsNested = False
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestCecil.InternalClass/PublicInnerInternalClass
  Name: PublicInnerInternalClass
  FullName: TestCecil.InternalClass/PublicInnerInternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = True

Type: TestCecil.InternalClass/InternalInnerInternalClass
  Name: InternalInnerInternalClass
  FullName: TestCecil.InternalClass/InternalInnerInternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = True
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestCecil.InternalClass/ProtectedInnerInternalClass
  Name: ProtectedInnerInternalClass
  FullName: TestCecil.InternalClass/ProtectedInnerInternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = True
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestCecil.InternalClass/ProtectedInternalInnerInternalClass
  Name: ProtectedInternalInnerInternalClass
  FullName: TestCecil.InternalClass/ProtectedInternalInnerInternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = True
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestCecil.InternalClass/PrivateInnerInternalClass
  Name: PrivateInnerInternalClass
  FullName: TestCecil.InternalClass/PrivateInnerInternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = True
  IsNestedPublic = False

Type: TestCecil.InternalClass/DefaultInnerInternalClass
  Name: DefaultInnerInternalClass
  FullName: TestCecil.InternalClass/DefaultInnerInternalClass
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = False
  IsPublic = False
  IsNotPublic = False
  IsNested = True
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = True
  IsNestedPublic = False

Type: TestCecil.InternalEnum
  Name: InternalEnum
  FullName: TestCecil.InternalEnum
  IsClass = True
  IsInterface = False
  IsEnum = True
  IsValueType = True
  IsPublic = False
  IsNotPublic = True
  IsNested = False
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False

Type: TestCecil.InternalStruct
  Name: InternalStruct
  FullName: TestCecil.InternalStruct
  IsClass = True
  IsInterface = False
  IsEnum = False
  IsValueType = True
  IsPublic = False
  IsNotPublic = True
  IsNested = False
  IsNestedAssembly = False
  IsNestedFamily = False
  IsNestedFamilyAndAssembly = False
  IsNestedFamilyOrAssembly = False
  IsNestedPrivate = False
  IsNestedPublic = False


注意Mono.Cecil在这个测试里与System.Reflection的差异:
1、使用Mono.Cecil的ModuleDefinition.Types能得到<Module>类的信息,而直接用System.Reflection的Assembly.GetTypes()不会得到这个类的信息;
2、System.Reflection使用加号('+')来连接外围类与内部类的名字,而Mono.Cecil使用斜杠('/');
3、System.Reflection的Type.IsClass对值类型返回false,而Mono.Cecil的TypeDefinition.IsClass对值类型返回true。(注意运行结果中红色的字)
MSDN上关于Type.IsClass的文档:
MSDN 写道
Gets a value indicating whether the Type is a class; that is, not a value type or interface.

可以认为这是Mono.Cecil的一个bug。前面提到,我用的是现在SVN trunk里的版本,也就是说这个问题可能之前一直都有。查看相关的实现:

Mono.Cecil/TypeAttributes.cs
[Flags]
public enum TypeAttributes : uint {
    // ...

    // Class semantics attributes
    ClassSemanticMask = 0x00000020, // Use this mask to retrieve class semantics information
    Class             = 0x00000000, // Type is a class
    Interface         = 0x00000020, // Type is an interface

    // ...
}


Mono.Cecil/TypeDefinition.cs
#region TypeAttributes

// ...

public bool IsClass {
    get { return (m_attributes & TypeAttributes.ClassSemanticMask) == TypeAttributes.Class; }
    set {
        if (value) {
            m_attributes &= ~TypeAttributes.ClassSemanticMask;
            m_attributes |= TypeAttributes.Class;
        } else
            m_attributes &= ~(TypeAttributes.ClassSemanticMask & TypeAttributes.Class);
    }
}

// ...

#endregion

public bool IsEnum {
    get { return m_baseType != null && m_baseType.FullName == Constants.Enum; }
}

public override bool IsValueType {
    get {
        return m_baseType != null && (
            this.IsEnum || (m_baseType.FullName == Constants.ValueType && this.FullName != Constants.Enum));
    }
}


要修正这个问题很简单,只要在TypeDefinition.IsClass的get方法的返回语句最后加上&& !this.IsValueType就行,变成这样:
public bool IsClass {
    get { return (m_attributes & TypeAttributes.ClassSemanticMask) == TypeAttributes.Class && !this.IsValueType; }
    // ...
}


修改后这个差异就消失了。

===========================================================================

另外也看到Mono.Cecil中的一些细微的可改进的地方(?)
ImageReader.cs
line 69: FileInfo fi = new FileInfo (file);
line 70: if (!File.Exists (fi.FullName))
或许在第70行用fi.Exists()就行了?
分享到:
评论
2 楼 RednaxelaFX 2008-09-22  
cajon 写道

Microsoft.Cci也很好用。FxCop中包含它的Assembly。但是似乎没有开源。有Reflactor,开不开源,似乎不重要了。:)

没错,不只FxCop里有Common Compiler Infrastructure(CCI)的assembly,另外一个地方也有:Zonnon,而且两者用的assembly还不完全一样。而且CCI确实是不开源的,是个神秘的项目。在Project 7和7+以外的我们能了解到的关于CCI的信息太少了。FxCop的SDK也迟迟未公开呢。
1 楼 cajon 2008-09-22  
Microsoft.Cci也很好用。FxCop中包含它的Assembly。但是似乎没有开源。
有Reflactor,开不开源,似乎不重要了。:)

相关推荐

Global site tag (gtag.js) - Google Analytics