C#的访问限制修饰符对应到Type的可见性属性有以下对应关系:
顶层类:
public -> IsPublic
internal -> IsNotPublic
(默认)-> internal -> IsNotPublic
嵌套类:
public -> IsNestedPublic
protected -> IsNestedFamily
protected internal -> IsNestedFamilyOrAssembly
private -> IsNestedPrivate
(默认)-> private -> IsNestedPrivate
[color=blue]注意:这些属性之中总是有且只有一个属性为真。一个嵌套类的Type只会显示自身的可见性,其外围类的可见性需要通过Type.DeclaringType找到其外围类的Type来查询。[/color]
C#无法表示IsFamANDAssem可见性的类型。
用一段代码通过System.Reflection来测试一下上述对应关系:
运行结果:
[quote]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 = [color=green][b]False[/b][/color]
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 = [color=green][b]False[/b][/color]
IsInterface = False
IsEnum = False
IsValueType = True
IsPublic = False
IsNotPublic = True
IsNested = False
IsNestedAssembly = False
IsNestedFamily = False
IsNestedFamilyAndAssembly = False
IsNestedFamilyOrAssembly = False
IsNestedPrivate = False
IsNestedPublic = False[/quote]
注意到嵌套类的全名中的'+',那是外围类的全名与嵌套类的类名连接的地方。
===========================================================================
用System.Reflection来加载assembly有一个缺点,那就是加载了的assembly在程序结束前无法卸载,会一直占用内存。为了绕开这个问题,可以用[url=http://www.mono-project.com/Cecil]Mono.Cecil[/url]来加载assembly并获取相关类型信息。
下面是用[url=svn://anonsvn.mono-project.com/source/trunk/mcs/class/Mono.Cecil]SVN trunk里的Mono.Cecil[/url]来做同样的测试:
运行结果:
[quote][color=blue]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[/color]
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 = [color=red][b]True[/b][/color]
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 = [color=red][b]True[/b][/color]
IsInterface = False
IsEnum = False
IsValueType = True
IsPublic = False
IsNotPublic = True
IsNested = False
IsNestedAssembly = False
IsNestedFamily = False
IsNestedFamilyAndAssembly = False
IsNestedFamilyOrAssembly = False
IsNestedPrivate = False
IsNestedPublic = False[/quote]
注意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上关于[url=http://msdn.microsoft.com/en-us/library/system.type.isclass.aspx]Type.IsClass[/url]的文档:
[quote="MSDN"]Gets a value indicating whether the Type is a class; that is, not a value type or interface.[/quote]
可以认为这是Mono.Cecil的一个bug。前面提到,我用的是现在SVN trunk里的版本,也就是说这个问题可能之前一直都有。查看相关的实现:
Mono.Cecil/TypeAttributes.cs
Mono.Cecil/TypeDefinition.cs
要修正这个问题很简单,只要在TypeDefinition.IsClass的get方法的返回语句最后加上&& !this.IsValueType就行,变成这样:
修改后这个差异就消失了。
===========================================================================
另外也看到Mono.Cecil中的一些细微的可改进的地方(?)
ImageReader.cs
line 69: FileInfo fi = new FileInfo (file);
line 70: if (!File.Exists (fi.FullName))
或许在第70行用fi.Exists()就行了?
顶层类:
public -> IsPublic
internal -> IsNotPublic
(默认)-> internal -> IsNotPublic
嵌套类:
public -> IsNestedPublic
protected -> IsNestedFamily
protected internal -> IsNestedFamilyOrAssembly
private -> IsNestedPrivate
(默认)-> private -> IsNestedPrivate
[color=blue]注意:这些属性之中总是有且只有一个属性为真。一个嵌套类的Type只会显示自身的可见性,其外围类的可见性需要通过Type.DeclaringType找到其外围类的Type来查询。[/color]
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 { }
}
运行结果:
[quote]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 = [color=green][b]False[/b][/color]
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 = [color=green][b]False[/b][/color]
IsInterface = False
IsEnum = False
IsValueType = True
IsPublic = False
IsNotPublic = True
IsNested = False
IsNestedAssembly = False
IsNestedFamily = False
IsNestedFamilyAndAssembly = False
IsNestedFamilyOrAssembly = False
IsNestedPrivate = False
IsNestedPublic = False[/quote]
注意到嵌套类的全名中的'+',那是外围类的全名与嵌套类的类名连接的地方。
===========================================================================
用System.Reflection来加载assembly有一个缺点,那就是加载了的assembly在程序结束前无法卸载,会一直占用内存。为了绕开这个问题,可以用[url=http://www.mono-project.com/Cecil]Mono.Cecil[/url]来加载assembly并获取相关类型信息。
下面是用[url=svn://anonsvn.mono-project.com/source/trunk/mcs/class/Mono.Cecil]SVN trunk里的Mono.Cecil[/url]来做同样的测试:
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 { }
}
运行结果:
[quote][color=blue]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[/color]
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 = [color=red][b]True[/b][/color]
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 = [color=red][b]True[/b][/color]
IsInterface = False
IsEnum = False
IsValueType = True
IsPublic = False
IsNotPublic = True
IsNested = False
IsNestedAssembly = False
IsNestedFamily = False
IsNestedFamilyAndAssembly = False
IsNestedFamilyOrAssembly = False
IsNestedPrivate = False
IsNestedPublic = False[/quote]
注意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上关于[url=http://msdn.microsoft.com/en-us/library/system.type.isclass.aspx]Type.IsClass[/url]的文档:
[quote="MSDN"]Gets a value indicating whether the Type is a class; that is, not a value type or interface.[/quote]
可以认为这是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()就行了?