65.9K
CodeProject 正在变化。 阅读更多。
Home

反射的一些时间

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (4投票s)

2010 年 8 月 27 日

CPOL

7分钟阅读

viewsIcon

21287

一篇解释 .NET 反射 API 中一些有价值方面的文章

引言

本文将重点介绍 .NET Framework 的反射 API。反射文档通常包含特性和编写动态代码,但我将避免后者,并尝试解释使用反射的一些更重要的方面,尽管它可能在编写实际应用程序中没有价值。相反,它确实有价值,并且精通它的人将能够使用反射来编写开发工具,甚至能够编写可以减少堆消耗的程序。为了初学者的重要理解,某些部分将逐步讲解一些源代码,以便掌握 C# 语法,但(在我有限的知识范围内)这篇文章可能接近中级水平。反射通常用于确定程序集定义了哪些类型。框架类库提供了许多获取此信息的方法,但最常用的方法是 Assembly 的 GetExportedTypes。下面是一些加载程序集并显示其中所有公共导出的类型名称的示例源代码。在解释了一些基本知识之后,输出将出现在下一节中。请检查此代码,然后我们将查看 Assembly 类的方法、属性和 static 方法。

using System;
using System.Reflection;
public static class Program {
public static void Main() {
String dataAssembly = "System.Data, version=4.0.0.0, " +
"culture=neutral, PublicKeyToken=b77a5c561934e089";
LoadAssemAndShowPublicTypes(dataAssembly);     
}
    
private static void LoadAssemAndShowPublicTypes(String assemId) {   
    Assembly a = Assembly.Load(assemId);   
foreach (Type t in a.GetExportedTypes()) {
Console.WriteLine(t.FullName);
             }
        }
} 

Assembly 类静态方法

  • GetAssembly
  • GetCallingAssembly
  • GetEntryAssembly
  • GetExecutingAssembly
  • Load (加载)
  • LoadFile
  • LoadFrom
  • ReflectionOnlyLoad
  • ReflectionOnlyLoadFrom

如您所见,GetExportedTypes 方法不是 static 的。请检查 Assembly 类的属性

  • EntryPoint
  • FullName
  • GlobalAssemblyCache
  • Location
  • ReflectionOnly

此时,检查语法非常重要。请检查此程序

using System;
using System.Reflection;
class Program {
static void Main(string[]  area)
{
   string path = @"C:\windows\Microsoft.net\Framework\v2.0.50727\System.dll";
   Assembly a = Assembly.LoadFile(path);
   ShowAssemblyInfo(a);
   Assembly ourAssembly = Assembly.GetExecutingAssembly();
   ShowAssemblyInfo(ourAssembly);
   Console.Read();
   }
   static void ShowAssemblyInfo(Assembly a)
   {
      Console.WriteLine(a.FullName);
      Console.WriteLine("From GAC? {0}", a.GlobalAssemblyCache);
      Console.WriteLine("Path:     {0}", a.Location);
      Console.WriteLine("Version:  {0}", a.ImageRuntimeVersion);

      foreach (Module m in a.GetModules())
      {
          Console.WriteLine("   Mod: {0}", m.Name);
      }

      Console.WriteLine();
    }
  } 

输出如下

c:\Windows\Microsoft.NET\Framework\v4.0.30319>getmod
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
From GAC? True
Path:     C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c
561934e089\System.dll
Version:  v4.0.30319
   Mod: System.dll

GetMod, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
From GAC? False
Path:     c:\Windows\Microsoft.NET\Framework\v4.0.30319\GetMod.exe
Version:  v4.0.30319
   Mod: GetMod.exe     

代码首先声明一个 string

string path = @"C:\windows\Microsoft.net\Framework\v2.0.50727\System.dll";

引用的 string 被存储在赋给 string 对象的“path”值中,因此“path”存储了左侧引号中包含的目录路径(其中包含要加载的程序集)。下一行代码实例化 Assembly 类。这被设置为等于 Assembly 类的 static 方法 LoadFile。请注意,此方法将上述路径(存储 string 的值)作为参数传递。另请注意,“a”后面紧跟着 Assembly 现在存储了该程序集的路径,因为它已被加载

Assembly a = Assembly.LoadFile(path); 

此时,我们编写一个 static 方法来显示有关当前加载程序集的信息。由于它正在执行,我们实例化另一个 Assembly 类的实例。static 方法 ShowAssemblyInfo 实现了它的名称所示的功能。初学者需要注意,原始值“a”作为传递给参数的 string 路径的引用,通过点语法写入以显示属性:(a.Location, a.GlobalAssemblyCache, a.FullName 等等。)以下是 Assembly 类的一些非 static 方法

  • CreateInstance
  • GetCustomAttributes
  • GetExportedTypes
  • GetModule
  • GetModules
  • GetTypes

话虽如此,让我们来看看原始源代码的输出。为简洁起见,请注意这些是(将近一半的)public 导出的类型

System.Text.RegularExpressions.Regex
System.Text.RegularExpressions.MatchEvaluator
System.Text.RegularExpressions.Capture
System.Text.RegularExpressions.CaptureCollection
System.Text.RegularExpressions.RegexCompilationInfo
System.Text.RegularExpressions.Group
System.Text.RegularExpressions.GroupCollection
System.Text.RegularExpressions.RegexRunner
System.Text.RegularExpressions.Match
System.Text.RegularExpressions.MatchCollection
System.Text.RegularExpressions.RegexOptions
System.Text.RegularExpressions.RegexRunnerFactory
System.CodeDom.CodeObject
System.CodeDom.CodeExpression
System.CodeDom.CodeArgumentReferenceExpression
System.CodeDom.CodeArrayCreateExpression
System.CodeDom.CodeArrayIndexerExpression
System.CodeDom.CodeStatement
System.CodeDom.CodeAssignStatement
System.CodeDom.CodeAttachEventStatement
System.CodeDom.CodeAttributeArgument
System.CodeDom.CodeAttributeArgumentCollection
System.CodeDom.CodeAttributeDeclaration
System.CodeDom.CodeAttributeDeclarationCollection
System.CodeDom.CodeBaseReferenceExpression
System.CodeDom.CodeBinaryOperatorExpression
System.CodeDom.CodeBinaryOperatorType
System.CodeDom.CodeCastExpression
System.CodeDom.CodeCatchClause
System.CodeDom.CodeCatchClauseCollection
System.CodeDom.CodeDirective
System.CodeDom.CodeChecksumPragma
System.CodeDom.CodeComment
System.CodeDom.CodeCommentStatement
System.CodeDom.CodeCommentStatementCollection
System.CodeDom.CodeCompileUnit
System.CodeDom.CodeConditionStatement
System.CodeDom.CodeTypeMember
System.CodeDom.CodeMemberMethod
System.CodeDom.CodeConstructor
System.CodeDom.CodeDefaultValueExpression
System.CodeDom.CodeDelegateCreateExpression
System.CodeDom.CodeDelegateInvokeExpression
System.CodeDom.CodeDirectionExpression
System.CodeDom.CodeDirectiveCollection
System.CodeDom.CodeEntryPointMethod
System.CodeDom.CodeEventReferenceExpression
System.CodeDom.CodeExpressionCollection
System.CodeDom.CodeExpressionStatement
System.CodeDom.CodeFieldReferenceExpression
System.CodeDom.CodeGotoStatement
System.CodeDom.CodeIndexerExpression
System.CodeDom.CodeIterationStatement
System.CodeDom.CodeLabeledStatement
System.CodeDom.CodeLinePragma
System.CodeDom.CodeMemberEvent
System.CodeDom.CodeMemberField
System.Net.FileWebResponse
System.Net.FtpStatusCode
……… etc ………………
System.Net.NetworkInformation.NetworkInterface
System.Net.NetworkInformation.NetworkInterfaceComponent
System.Net.NetworkInformation.NetBiosNodeType
System.Net.NetworkInformation.OperationalStatus
System.Net.NetworkInformation.PhysicalAddress
System.Net.NetworkInformation.PingCompletedEventHandler
System.Net.NetworkInformation.PingCompletedEventArgs
System.Net.NetworkInformation.Ping
System.Net.NetworkInformation.PingException
System.Net.NetworkInformation.PingOptions
System.Net.NetworkInformation.PingReply
System.Net.NetworkInformation.PrefixOrigin
System.Net.NetworkInformation.SuffixOrigin
System.Net.NetworkInformation.TcpConnectionInformation
System.Net.NetworkInformation.TcpStatistics
System.Net.NetworkInformation.UdpStatistics
System.Net.NetworkInformation.TcpState
System.Net.Configuration.AuthenticationModuleElement
System.Net.Configuration.AuthenticationModuleElementCollection
System.Net.Configuration.AuthenticationModulesSection
System.Net.Configuration.BypassElement
System.Net.Configuration.BypassElementCollection
System.Net.Configuration.ConnectionManagementElement
System.Net.Configuration.ConnectionManagementElementCollection
System.Net.Configuration.ConnectionManagementSection
System.Net.Configuration.DefaultProxySection
System.Net.Configuration.HttpWebRequestElement
System.Net.Configuration.HttpListenerElement
System.Net.Configuration.HttpCachePolicyElement
System.Net.Configuration.FtpCachePolicyElement
System.Net.Configuration.Ipv6Element
System.Net.Configuration.MailSettingsSectionGroup
System.Net.Configuration.ModuleElement
System.Net.Configuration.NetSectionGroup
System.Net.Configuration.PerformanceCountersElement
System.Net.Configuration.ProxyElement
System.Net.Configuration.ProxyElement+BypassOnLocalValues
System.Net.Configuration.ProxyElement+UseSystemDefaultValues
System.Net.Configuration.ProxyElement+AutoDetectValues
System.Net.Configuration.RequestCachingSection
System.Configuration.SchemeSettingElement
System.Configuration.SchemeSettingElementCollection
System.Net.Configuration.SettingsSection
System.Net.Configuration.ServicePointManagerElement
System.Net.Configuration.SmtpSection
System.Net.Configuration.SmtpNetworkElement
System.Net.Configuration.SmtpSpecifiedPickupDirectoryElement
System.Net.Configuration.SocketElement
…..etc….
System.Diagnostics.FileVersionInfo
System.Diagnostics.ICollectData
System.Diagnostics.InstanceData
System.Diagnostics.InstanceDataCollection
System.Diagnostics.InstanceDataCollectionCollection
System.Diagnostics.MonitoringDescriptionAttribute
System.Diagnostics.OverflowAction
System.Diagnostics.PerformanceCounter
System.Diagnostics.PerformanceCounterCategory
System.Diagnostics.PerformanceCounterCategoryType
System.Diagnostics.PerformanceCounterInstanceLifetime
System.Diagnostics.PerformanceCounterManager
System.Diagnostics.PerformanceCounterPermission
System.Diagnostics.PerformanceCounterPermissionAccess
System.Diagnostics.PerformanceCounterPermissionAttribute
System.Diagnostics.PerformanceCounterPermissionEntry
System.Diagnostics.PerformanceCounterPermissionEntryCollection
System.Diagnostics.PerformanceCounterType
System.Diagnostics.Process
System.Diagnostics.ProcessModule
System.Diagnostics.ProcessModuleCollection
System.Diagnostics.ProcessPriorityClass
System.Diagnostics.ProcessStartInfo
System.Diagnostics.ProcessThread
System.Diagnostics.ProcessThreadCollection
System.Diagnostics.ProcessWindowStyle
System.Diagnostics.Stopwatch
System.Diagnostics.ThreadPriorityLevel
System.Diagnostics.ThreadState
System.Diagnostics.ThreadWaitReason
System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute
System.Configuration.AppSettingsReader
System.IO.Ports.Handshake
System.IO.Ports.Parity
System.IO.Ports.SerialError
System.IO.Ports.SerialErrorReceivedEventArgs
System.IO.Ports.SerialErrorReceivedEventHandler
System.IO.Ports.SerialPinChange
System.IO.Ports.SerialPinChangedEventArgs
System.IO.Ports.SerialPinChangedEventHandler
System.IO.Ports.SerialPort
System.IO.Ports.SerialData
System.IO.Ports.SerialDataReceivedEventArgs
System.IO.Ports.SerialDataReceivedEventHandler
System.IO.Ports.StopBits   

那个对象是什么类型?

或者,什么是 Type 对象?众所周知,.NET 中的所有对象都派生自 System.Object。该根命名空间中定义的方法之一是 GetType。请注意,前面的代码迭代了一个 System.Type 对象数组。System.Type 类型是进行类型和对象操作的起点。System.Type 是一个抽象基类型,派生自 System.Reflection.MemberInfo(因为一个 Type 可以是另一个类型的成员)。FCL 提供了几种派生自 System.Type 的类型:System.RuntimeType、System.ReflectionOnlyType、System.Reflection.TypeDelegator,以及 System.Reflection.Emit 命名空间中定义的一些类型(EnumBuilder、GenericTypeParameterBuilder 和 TypeBuilder)。Object 类支持的 GetType 方法返回一个 Type 对象,该对象引用对象的实际 Type。例如,让我们创建一个 Animal 类,然后创建两个派生自 Animal 类的类

using System;
public class Animal
   {
   }
public class Dog : Animal
   {
   }
public class Cat : Animal
   {
   }
class App {
static void Main() {
Animal aAnim = new Animal();
Animal aDog = new Dog();
Animal aCat = new Cat();
Console.WriteLine("Typename for aAnim is {0}", aAnim.GetType().Name);
Console.WriteLine("Typename for aDog is {0}", aDog.GetType().Name);
Console.WriteLine("Typename for aCat is  {0}", aCat.GetType().Name);
 }
}   

输出符合预期。请注意“typeof”关键字的使用

Typename for aAnim is Animal
Typename for aDog   is Dog
Typename for aCat   is  Cat  

要为泛型类型构造实例,首先获取对开放类型的引用,然后调用 Type 的 public 实例 MakeGenericType 方法,并传入要用作类型参数的类型数组。然后,获取返回的 Type 对象,并将其传递给上面列出的各种方法之一。这是一个例子

using System; 
using System.Reflection; 
using System.Collections.Generic; 
using System.Linq; 
internal sealed class Dictionary { } 
public static class Program { 
public static void Main() 
{ 
Type openType = typeof(Dictionary<,>); 
Type closedType = openType.MakeGenericType(typeof(String), 
	typeof(Int32)); Object o = Activator.CreateInstance(closedType); 
Console.WriteLine(o.GetType()); 
} 
}  

编译此代码时,应得到以下结果

Dictionary`2[System.String,System.Int32]    

使用反射发现类型的成员

根据微软的技术文档,发现和调用类型成员的能力通常用于创建开发人员工具和实用程序,这些工具和实用程序通过查找特定编程模式或成员的使用来分析程序集。执行此操作的工具/实用程序的示例包括 ILDasm.exeFxCopCmd.exe 以及 Visual Studio 的 Windows Forms 和 Web 设计器。

字段、构造函数、方法、属性、事件和嵌套类型都可以定义为类型内的成员。FCL 包含一个名为 System.Reflection.MemberInfo 的类型。此类是抽象基类,封装了所有类型成员共有的许多属性。从 MemberInfo 派生出来的是一堆类;每个类都封装了与特定类型成员相关的更多属性。下面是这些类型的分层列表

System.Object
System.Reflection.MemberInfo
System.Type
System.Reflection.FieldInfo
System.Reflection.MethodBase
System.Reflection.ContructorInfo
System.Reflection.MethodInfo
System.Reflection.PropertyInfo
System.Reflection.EventInfo    

对于每种类型,都会调用 GetMembers 方法,并返回一个 MemberInfo 派生对象的数组;每个对象都引用类型中定义的单个成员。传递给 GetMembers 方法的 BindingFlags 变量 bf 告诉方法返回哪些类型的成员。然后,对于每个成员,将显示其类型(字段、构造函数、方法、属性等)及其 string 值(通过调用 ToString 获取)。BindingFlags 主题稍后将进行讨论。请研究此代码

using System;
using System.Reflection;
public static class Program {
public static void Main() {
// Loop through all assemblies loaded in this AppDomain
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly a in assemblies) {
WriteLine(0, "Assembly: {0}", a);
// Find Types in the assembly
foreach (Type t in a.GetExportedTypes()) {
WriteLine(1, "Type: {0}", t);
// Discover the type's members
const BindingFlags bf = BindingFlags.DeclaredOnly |
BindingFlags.NonPublic | BindingFlags.Public |
BindingFlags.Instance | BindingFlags.Static;
foreach (MemberInfo mi in t.GetMembers(bf)) {
String typeName = String.Empty;
if (mi is Type) typeName = "(Nested) Type";
else if (mi is FieldInfo) typeName = "FieldInfo";
else if (mi is MethodInfo) typeName = "MethodInfo";
else if (mi is ConstructorInfo) typeName = "ConstructoInfo";
else if (mi is PropertyInfo) typeName = "PropertyInfo";
else if (mi is EventInfo) typeName = "EventInfo";
WriteLine(2, "{0}: {1}", typeName, mi);
    }
  }
 }
}
 private static void WriteLine(Int32 indent, String format, params Object[] args) {
Console.WriteLine(new String(' ', 3 * indent) + format, args);
  }
}

编译的代码运行时会输出大量信息。这是输出的一小部分示例,请尝试与分层列表建立联系。

Assembly: mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
   Type: System.Object
      MethodInfo: System.String ToString()
      MethodInfo: Boolean Equals(System.Object)
      MethodInfo: Boolean Equals(System.Object, System.Object)
      MethodInfo: Boolean ReferenceEquals(System.Object, System.Object)
      MethodInfo: Int32 GetHashCode()
      MethodInfo: System.Type GetType()
      MethodInfo: Void Finalize()
      MethodInfo: System.Object MemberwiseClone()
      MethodInfo: Void FieldSetter(System.String, System.String, System.Object)
      MethodInfo: Void FieldGetter(System.String, System.String, System.Object ByRef)
      MethodInfo: System.Reflection.FieldInfo GetFieldInfo(System.String, System.String)
      ConstructoInfo: Void .ctor()
   Type: System.Runtime.Serialization.ISerializable
      MethodInfo: Void GetObjectData(System.Runtime.Serialization.SerializationInfo, 
	System.Runtime.Serialization.StreamingContext)
   Type: System.Runtime.InteropServices._Exception
      MethodInfo: System.String ToString()
      MethodInfo: Boolean Equals(System.Object)
      MethodInfo: Int32 GetHashCode()
      MethodInfo: System.Type GetType()
      MethodInfo: System.String get_Message()
      MethodInfo: System.Exception GetBaseException()
      MethodInfo: System.String get_StackTrace()
      MethodInfo: System.String get_HelpLink()
      MethodInfo: Void set_HelpLink(System.String)
      MethodInfo: System.String get_Source()
      MethodInfo: Void set_Source(System.String)
      MethodInfo: Void GetObjectData(System.Runtime.Serialization.SerializationInfo, 
	System.Runtime.Serialization.StreamingContext)
      MethodInfo: System.Exception get_InnerException()
      MethodInfo: System.Reflection.MethodBase get_TargetSite()
      PropertyInfo: System.String Message
      PropertyInfo: System.String StackTrace
      PropertyInfo: System.String HelpLink
      PropertyInfo: System.String Source
      PropertyInfo: System.Exception InnerException
      PropertyInfo: System.Reflection.MethodBase TargetSite
   Type: System.Exception
      MethodInfo: System.String get_Message()
      MethodInfo: System.Collections.IDictionary get_Data()
      MethodInfo: System.Exception GetBaseException()
      MethodInfo: System.Exception get_InnerException()
      MethodInfo: System.Reflection.MethodBase get_TargetSite()
      MethodInfo: System.Reflection.MethodBase GetTargetSiteInternal()
      MethodInfo: System.String get_StackTrace()
      MethodInfo: System.String GetStackTrace(Boolean)
      MethodInfo: Void SetErrorCode(Int32)
      MethodInfo: System.String get_HelpLink()
      MethodInfo: Void set_HelpLink(System.String)
      MethodInfo: System.String get_Source()
      MethodInfo: Void set_Source(System.String)
      MethodInfo: System.String ToString()
      MethodInfo: System.String ToString(Boolean)
      MethodInfo: Void add_SerializeObjectState
	(System.EventHandler`1[System.Runtime.Serialization.SafeSerializationEventArgs])
      MethodInfo: Void remove_SerializeObjectState
	(System.EventHandler`1[System.Runtime.Serialization.SafeSerializationEventArgs])
      MethodInfo: Void GetObjectData
	(System.Runtime.Serialization.SerializationInfo, 
	System.Runtime.Serialization.StreamingContext)
      MethodInfo: System.Exception PrepForRemoting()
      MethodInfo: Void InternalPreserveStackTrace()
      MethodInfo: Int32 get_HResult()
      MethodInfo: Void set_HResult(Int32)
      MethodInfo: System.String InternalToString()
      MethodInfo: System.Type GetType()
      MethodInfo: Boolean get_IsTransient()
      MethodInfo: System.String GetMessageFromNativeResources(ExceptionMessageKind)
      MethodInfo: Void Init()
      MethodInfo: Boolean IsImmutableAgileException(System.Exception)
      MethodInfo: System.String GetClassName()
      MethodInfo: System.IRuntimeMethodInfo GetMethodFromStackTrace(System.Object)
      MethodInfo: System.Reflection.MethodBase GetExceptionMethodFromStackTrace()
      MethodInfo: System.String GetExceptionMethodString()
      MethodInfo: System.Reflection.MethodBase GetExceptionMethodFromString()
      MethodInfo: Void OnDeserialized(System.Runtime.Serialization.StreamingContext)
      MethodInfo: Boolean nIsTransient(Int32)
      MethodInfo: Void GetMessageFromNativeResources
	(ExceptionMessageKind, System.Runtime.CompilerServices.StringHandleOnStack)
      ConstructoInfo: Void .ctor()
      ConstructoInfo: Void .ctor(System.String)
      ConstructoInfo: Void .ctor(System.String, System.Exception)
      ConstructoInfo: Void .ctor
	(System.Runtime.Serialization.SerializationInfo, 
	System.Runtime.Serialization.StreamingContext)
      PropertyInfo: System.String Message
      PropertyInfo: System.Collections.IDictionary Data
      PropertyInfo: System.Exception InnerException
      PropertyInfo: System.Reflection.MethodBase TargetSite
      PropertyInfo: System.String StackTrace
      PropertyInfo: System.String HelpLink
      PropertyInfo: System.String Source
      PropertyInfo: Int32 HResult
      PropertyInfo: Boolean IsTransient
      EventInfo: System.EventHandler`1
	[System.Runtime.Serialization.SafeSerializationEventArgs] SerializeObjectState
      FieldInfo: System.String _className
      FieldInfo: System.Reflection.MethodBase _exceptionMethod
      FieldInfo: System.String _exceptionMethodString
      FieldInfo: System.String _message
      FieldInfo: System.Collections.IDictionary _data
      FieldInfo: System.Exception _innerException
      FieldInfo: System.String _helpURL
      FieldInfo: System.Object _stackTrace
      FieldInfo: System.Object _watsonBuckets
      FieldInfo: System.String _stackTraceString
      FieldInfo: System.String _remoteStackTraceString
      FieldInfo: Int32 _remoteStackIndex
      FieldInfo: System.Object _dynamicMethods
      FieldInfo: Int32 _HResult
      FieldInfo: System.String _source
      FieldInfo: IntPtr _xptrs
      FieldInfo: Int32 _xcode
      FieldInfo: UIntPtr _ipForWatsonBuckets
      FieldInfo: System.Runtime.Serialization.SafeSerializationManager 
		_safeSerializationManager
      FieldInfo: Int32 _COMPlusExceptionCode
      (Nested) Type: System.Exception+ExceptionMessageKind
   Type: System.ValueType
      MethodInfo: Boolean Equals(System.Object)
      MethodInfo: Int32 GetHashCode()
      MethodInfo: Int32 GetHashCodeOfPtr(IntPtr)
      MethodInfo: System.String ToString()
      MethodInfo: Boolean CanCompareBits(System.Object)
      MethodInfo: Boolean FastEqualsCheck(System.Object, System.Object)
      ConstructoInfo: Void .ctor()       

使用 BindingFlags

BindingFlags 枚举用于控制如何使用 GetMembers 方法检索类型的成员,以及每个成员类型的特定成员。更确切地说,BindingFlags 会过滤返回的成员类型。您可以通过调用 Type 的 GetMembersGetNestedTypesGetFieldsGetConstructorsGetMethodsGetPropertiesGetEvents 方法来查询类型的成员。调用这些方法中的任何一个时,都可以传递 System.Reflection.BindingFlags 枚举类型的实例。该枚举类型标识了一组位标志,这些标志通过 OR 运算组合在一起,以帮助您过滤从这些方法返回的成员。尽管我们在最后一个示例中使用了 BindingFlags,但这是例证其直接目的的源代码

using System;
using System.Reflection;
public class Program
 {
    public static void Main(string[]  args)
    {
      string path = @"C:\Windows\Microsoft.NET\Framework\v2.0.50727\" +
      "System.ServiceProcess.dll";

       // using BindingFlags to only get the declared
       // and instance members

       BindingFlags flags =
       BindingFlags.DeclaredOnly |
       BindingFlags.Public |
       BindingFlags.Instance;

       Assembly a = Assembly.LoadFrom(path);
       Console.WriteLine(a.FullName);

       Type[] types = a.GetTypes();

       foreach ( Type t in types )
       {
         Console.WriteLine("  Type:  {0}", t.Name);
         MemberInfo[] m = t.GetMembers(flags);

       foreach (MemberInfo member in m)
        {
           Console.WriteLine("  {0}: {1}", member.MemberType, member.Name);
        }
       }

       Console.Read();
     }
  }  

当我们运行编译后的代码时,我们将看到(和往常一样,有很多信息).NET 使用 API 返回信息类型,这些类型接受 BindingFlags 标志式枚举值来将搜索限制在具有某些属性的抽象上

System.ServiceProcess, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
  Type:  NativeMethods
  NestedType: SERVICE_STATUS
  NestedType: ServiceMainCallback
  NestedType: ServiceControlCallback
  NestedType: ServiceControlCallbackEx
  NestedType: StructFormat
  NestedType: ENUM_SERVICE_STATUS
  NestedType: ENUM_SERVICE_STATUS_PROCESS
  NestedType: QUERY_SERVICE_CONFIG
  NestedType: SERVICE_TABLE_ENTRY
  NestedType: LSA_UNICODE_STRING
  NestedType: LSA_UNICODE_STRING_withPointer
  NestedType: LSA_OBJECT_ATTRIBUTES
  NestedType: SERVICE_DESCRIPTION
  NestedType: SERVICE_DELAYED_AUTOSTART_INFO
  NestedType: SERVICE_FAILURE_ACTIONS
  NestedType: SC_ACTION
  NestedType: WTSSESSION_NOTIFICATION
  Type:  SERVICE_STATUS
  Field: serviceType
  Field: currentState
  Field: controlsAccepted
  Field: win32ExitCode
  Field: serviceSpecificExitCode
  Field: checkPoint
  Field: waitHint
  Type:  ServiceMainCallback
  Method: Invoke
  Method: BeginInvoke
  Method: EndInvoke
  Constructor: .ctor
  Type:  ServiceControlCallback
  Method: Invoke
  Method: BeginInvoke
  Method: EndInvoke
  Constructor: .ctor
  Type:  ServiceControlCallbackEx
  Method: Invoke
  Method: BeginInvoke
  Method: EndInvoke
  Constructor: .ctor
  Type:  PowerBroadcastStatus
  Field: value__
  Type:  SafeNativeMethods
  Type:  ServiceAccount
  Field: value__
  Type:  ServiceBase
  Method: RequestAdditionalTime
  Method: get_AutoLog
  Method: set_AutoLog
  Method: get_ExitCode
  Method: set_ExitCode
  Method: get_CanHandlePowerEvent
  Method: set_CanHandlePowerEvent
  Method: get_CanHandleSessionChangeEvent
  Method: set_CanHandleSessionChangeEvent
  Method: get_CanPauseAndContinue
  Method: set_CanPauseAndContinue
  Method: get_CanShutdown
  Method: set_CanShutdown
  Method: get_CanStop
  Method: set_CanStop
  Method: get_EventLog
  Method: get_ServiceName
  Method: set_ServiceName
  Method: Stop
  Method: ServiceMainCallback
  Constructor: .ctor
  Property: AutoLog
  Property: ExitCode
  Property: CanHandlePowerEvent
  Property: CanHandleSessionChangeEvent
  Property: CanPauseAndContinue
  Property: CanShutdown
  Property: CanStop
  Property: EventLog
  Property: ServiceName
  Type:  ServiceController
  Method: get_CanPauseAndContinue
  Method: get_CanShutdown
  Method: get_CanStop
  Method: get_DisplayName
  Method: set_DisplayName
  Method: get_DependentServices
  Method: get_MachineName
  Method: set_MachineName
  Method: get_ServiceName
  Method: set_ServiceName
  Method: get_ServicesDependedOn
  Method: get_ServiceHandle
  Method: get_Status
  Method: get_ServiceType
  Method: Close
  Method: Pause
  Method: Continue
  Method: ExecuteCommand
  Method: Refresh
  Method: Start
  Method: Start
  Method: Stop
  Method: WaitForStatus
  Method: WaitForStatus
  Constructor: .ctor
  Constructor: .ctor
  Constructor: .ctor
  Property: CanPauseAndContinue
  Property: CanShutdown
  Property: CanStop
  Property: DisplayName
  Property: DependentServices
  Property: MachineName
  Property: ServiceName
  Property: ServicesDependedOn
  Property: ServiceHandle
  Property: Status
  Property: ServiceType
  Type:  ServiceControllerPermission
  Method: get_PermissionEntries
  Constructor: .ctor
  Constructor: .ctor
  Constructor: .ctor
  Constructor: .ctor
  Property: PermissionEntries
  Type:  ServiceControllerPermissionAccess
  Field: value__
  Type:  ServiceControllerPermissionAttribute
  Method: get_MachineName
  Method: set_MachineName
  Method: get_PermissionAccess
  Method: set_PermissionAccess
  Method: get_ServiceName
  Method: set_ServiceName
  Method: CreatePermission
  Constructor: .ctor
  Property: MachineName
  Property: PermissionAccess
  Property: ServiceName
  Type:  ServiceControllerPermissionEntry
  Method: get_MachineName
  Method: get_PermissionAccess
  Method: get_ServiceName
  Constructor: .ctor
  Constructor: .ctor
  Property: MachineName
  Property: PermissionAccess
  Property: ServiceName
  Type:  ServiceControllerPermissionEntryCollection
  Method: get_Item
  Method: set_Item
  Method: Add
  Method: AddRange
  Method: AddRange
  Method: Contains
  Method: CopyTo
  Method: IndexOf
  Method: Insert
  Method: Remove
  Property: Item
  Type:  ServiceControllerStatus
  Field: value__
  Type:  ServiceInstaller
  Method: get_DisplayName
  Method: set_DisplayName
  Method: get_Description
  Method: set_Description
  Method: get_ServicesDependedOn
  Method: set_ServicesDependedOn
  Method: get_ServiceName
  Method: set_ServiceName
  Method: get_StartType
  Method: set_StartType
  Method: get_DelayedAutoStart
  Method: set_DelayedAutoStart
  Method: CopyFromComponent
  Method: Install
  Method: IsEquivalentInstaller
  Method: Rollback
  Method: Uninstall
  Constructor: .ctor
  Property: DisplayName
  Property: Description
  Property: ServicesDependedOn
  Property: ServiceName
  Property: StartType
  Property: DelayedAutoStart
  Type:  ServiceProcessDescriptionAttribute
  Method: get_Description
  Constructor: .ctor
  Property: Description
  Type:  ServiceProcessInstaller
  Method: get_HelpText
  Method: get_Password
  Method: set_Password
  Method: get_Account
  Method: set_Account
  Method: get_Username
  Method: set_Username
  Method: CopyFromComponent
  Method: Install
  Method: Rollback
  Constructor: .ctor
  Property: HelpText
  Property: Password
  Property: Account
  Property: Username
  Type:  ServiceStartMode
  Field: value__
  Type:  ServiceType
  Field: value__
  Type:  SessionChangeReason
  Field: value__
  Type:  SessionChangeDescription
  Method: get_Reason
  Method: get_SessionId
  Method: Equals
  Method: GetHashCode
  Method: Equals
  Property: Reason
  Property: SessionId
  Type:  TimeoutException
  Constructor: .ctor
  Constructor: .ctor
  Constructor: .ctor
  Type:  ServiceInstallerDialogResult
  Field: value__
  Type:  ServiceInstallerDialog
  Method: get_Password
  Method: set_Password
  Method: get_Result
  Method: get_Username
  Method: set_Username
  Constructor: .ctor
  Property: Password
  Property: Result
  Property: Username
  Type:  FXAssembly
  Type:  ThisAssembly
  Type:  AssemblyRef
  Type:  ResDescriptionAttribute
  Method: get_Description
  Constructor: .ctor
  Property: Description
  Type:  ResCategoryAttribute
  Constructor: .ctor
  Type:  Res
  Type:  ExternDll
  Type:  HResults
  Type:  StructFormat
  Field: value__
  Type:  ENUM_SERVICE_STATUS
  Constructor: .ctor
  Field: serviceName
  Field: displayName
  Field: serviceType
  Field: currentState
  Field: controlsAccepted
  Field: win32ExitCode
  Field: serviceSpecificExitCode
  Field: checkPoint
  Field: waitHint
  Type:  ENUM_SERVICE_STATUS_PROCESS
  Constructor: .ctor
  Field: serviceName
  Field: displayName
  Field: serviceType
  Field: currentState
  Field: controlsAccepted
  Field: win32ExitCode
  Field: serviceSpecificExitCode
  Field: checkPoint
  Field: waitHint
  Field: processID
  Field: serviceFlags
  Type:  QUERY_SERVICE_CONFIG
  Constructor: .ctor
  Field: dwServiceType
  Field: dwStartType
  Field: dwErrorControl
  Field: lpBinaryPathName
  Field: lpLoadOrderGroup
  Field: dwTagId
  Field: lpDependencies
  Field: lpServiceStartName
  Field: lpDisplayName
  Type:  SERVICE_TABLE_ENTRY
  Constructor: .ctor
  Field: name
  Field: callback
  Type:  LSA_UNICODE_STRING
  Constructor: .ctor
  Field: length
  Field: maximumLength
  Field: buffer
  Type:  LSA_UNICODE_STRING_withPointer
  Constructor: .ctor
  Field: length
  Field: maximumLength
  Field: pwstr
  Type:  LSA_OBJECT_ATTRIBUTES
  Constructor: .ctor
  Field: length
  Field: rootDirectory
  Field: pointerLsaString
  Field: attributes
  Field: pointerSecurityDescriptor
  Field: pointerSecurityQualityOfService
  Type:  SERVICE_DESCRIPTION
  Field: description
  Type:  SERVICE_DELAYED_AUTOSTART_INFO
  Field: fDelayedAutostart
  Type:  SERVICE_FAILURE_ACTIONS
  Field: dwResetPeriod
  Field: rebootMsg
  Field: command
  Field: numActions
  Field: actions
  Type:  SC_ACTION
  Field: type
  Field: delay
  Type:  WTSSESSION_NOTIFICATION
  Constructor: .ctor
  Field: size
  Field: sessionId
  Type:  SafeServiceHandle
  Type:  DeferredHandlerDelegate
  Method: Invoke
  Method: BeginInvoke
  Method: EndInvoke
  Constructor: .ctor
  Type:  DeferredHandlerDelegateCommand
  Method: Invoke
  Method: BeginInvoke
  Method: EndInvoke
  Constructor: .ctor
  Type:  DeferredHandlerDelegateAdvanced
  Method: Invoke
  Method: BeginInvoke
  Method: EndInvoke
  Constructor: .ctor
  Type:  UnsafeNativeMethods
  Type:  ServiceNameConverter
  Method: CanConvertFrom
  Method: ConvertFrom
  Method: GetStandardValues
  Method: GetStandardValuesExclusive
  Method: GetStandardValuesSupported
  Constructor: .ctor       

总之,请记住,C# 编译器会发出元数据和 IL 代码。元数据存储在一堆表中。构建程序集或模块时,使用的编译器会创建一个类型定义表、字段定义表、方法定义表等。System.Reflection 命名空间包含几种类型,允许您编写代码来反射(或解析)这些元数据表。实际上,此命名空间中的类型提供了对程序集或模块中包含的元数据的对象模型。使用这些对象模型类型,您可以轻松地枚举类型定义元数据表中的所有类型。然后,对于每种类型,您可以获取其基类型、它实现的接口以及与该类型关联的标志。System.Reflection 命名空间中的其他类型允许您通过解析相应的元数据表来查询类型的字段、方法、属性和事件。如果您想编写一个可以使用的程序集,请转储一个程序集并研究其信息。一个非常有用的工具正是用于此目的,名为 .NET Reflector。

参考文献

  • Joe Duffy 著《Professional .NET Framework 2.0》

历史

  • 2010 年 8 月 27 日:初次发布
© . All rights reserved.