18.1.1 Assembly

1.加载程序集

 

代码
Imports System.Reflection

Module LoadAssembly
Dim asm As Assembly

' Get a reference to the assembly
Sub a()

' Get a reference to the assembly this code is running in.
asm = Assembly.GetExecutingAssembly()

' Get a reference to the assembly a type belongs to.
asm = Assembly.GetAssembly(GetType(System.Data.DataSet))

' Another way to reach the same result.
asm = GetType(System.Data.DataSet).Assembly

' Get a reference to an assembly given its display name.
' (The argument can be the assembly's full name, which includes
' version, culture, and public key.)
asm = Assembly.Load("mscorlib")

' Get a reference to an assembly given its filename or its full name.
asm = Assembly.LoadFrom("c:\myapp\mylib.dll")

' Another way to get a reference to an assembly given its path. (See text for notes.)
asm = Assembly.LoadFile("c:\myapp\mylib.dll")
End Sub

'Assemblies referenced by current assembly:
Sub b()
For Each refAsm As Assembly In AppDomain.CurrentDomain.GetAssemblies()
Console.WriteLine(refAsm.FullName)
Next
End Sub

Sub c()
' Load the System.Data.dll for reflection purposes.
asm = Assembly.ReflectionOnlyLoad(
"System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")

' Load a file for reflection purposes, given its path.
asm = Assembly.ReflectionOnlyLoadFrom("c:\myapp\mylib.dll")
End Sub

'Assemblies loaded for reflection purposes only:
Sub d()
For Each refAsm As Assembly In AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies()
Console.WriteLine(refAsm.FullName)
Next
End Sub

End Module

 

 

2. AppDomain事件

 

代码
Sub AppDomainLoadAssemblyEvent()
' Subscribe to AppDomain event.
Dim appDom As AppDomain = AppDomain.CurrentDomain
AddHandler appDom.AssemblyLoad, AddressOf AppDomain_AssemblyLoad

' This statement causes the JIT-compilation of DoSomethingWithXml method
' which in turns loads the System.Xml.dll assembly
DoSomethingWithXml()
Console.WriteLine()

' Unsubscribe from event.
RemoveHandler appDom.AssemblyLoad, AddressOf AppDomain_AssemblyLoad
End Sub

Private Sub DoSomethingWithXml()
' This statement causes the loading of the System.Xml.dll assembly.
Dim doc As New System.Xml.XmlDocument()
End Sub

Private Sub AppDomain_AssemblyLoad(ByVal sender As Object, ByVal e As AssemblyLoadEventArgs)
Console.WriteLine(
"Assembly {0} is being loaded", e.LoadedAssembly.Location)
End Sub

Sub AppDomainAssemblyResolveEvent()
' Subscribe to AppDomain event.
Dim appDom As AppDomain = AppDomain.CurrentDomain
AddHandler appDom.AssemblyResolve, AddressOf AppDomain_AssemblyResolve
AddHandler appDom.ReflectionOnlyAssemblyResolve, AddressOf AppDomain_ReflectionOnlyAssemblyResolve

' Attempt to load an assembly that isn't in the private path.
'Dim asm As Assembly = Assembly.Load("EvaluatorLibrary")
'Console.WriteLine("Found {0} assembly at {1}", asm.FullName, asm.Location)

Dim asm As Assembly = Assembly.ReflectionOnlyLoad("EvaluatorLibrary")
Console.WriteLine(
"Found {0} assembly at {1}", asm.FullName, asm.Location)

' Unsubscribe from events.
RemoveHandler appDom.AssemblyResolve, AddressOf AppDomain_AssemblyResolve
RemoveHandler appDom.ReflectionOnlyAssemblyResolve, AddressOf AppDomain_ReflectionOnlyAssemblyResolve
End Sub

Private Function AppDomain_AssemblyResolve(ByVal sender As Object, ByVal e As ResolveEventArgs) As Assembly
' Search the assembly two levels up in the directory tree.
Dim searchDir As String = Path.GetFullPath(".\..\..")
For Each dllFile As String In Directory.GetFiles(searchDir, "*.dll")
Try
Dim asm As Assembly = Assembly.LoadFile(dllFile)
' If the DLL is an assembly and its name matches, we've found it.
If asm.GetName().Name = e.Name Then Return asm
Catch ex As Exception
' Ignore DLLs that aren't valid assemblies.
End Try
Next
' If we get here, return Nothing to signal that the search failed.
Return Nothing
End Function

Private Function AppDomain_ReflectionOnlyAssemblyResolve(ByVal sender As Object, ByVal e As ResolveEventArgs) As Assembly
' Search the assembly two levels up in the directory tree.
Dim searchDir As String = Path.GetFullPath(".\..\..")
For Each dllFile As String In Directory.GetFiles(searchDir, "*.dll")
Try
Dim asm As Assembly = Assembly.LoadFile(dllFile)
' If the DLL is an assembly and its name matches, we've found it.
If asm.GetName().Name = e.Name Then Return asm
Catch ex As Exception
' Ignore DLLs that aren't valid assemblies.
End Try
Next
' If we get here, return Nothing to signal that the search failed.
Return Nothing
End Function

 

3. 属性和方法

 

代码
Imports System.Reflection

Module Module2
'---------------------------------------------------------
' Assembly's properties and methods
'---------------------------------------------------------
Dim asm As Assembly

' This is the ADO.NET assembly.
Sub a()
asm
= GetType(System.Data.DataSet).Assembly
Debug.Assert(asm.FullName
=
"System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
Debug.Assert(asm.Location
=
"C:\WINDOWS\assembly\GAC_32\System.Data\2.0.0.0__b77a5c561934e089\System.Data.dll")
Debug.Assert(asm.CodeBase
=
"file:///C:/WINDOWS/assembly/GAC_32/System.Data/2.0.0.0__b77a5c561934e089/System.Data.dll")
End Sub

' Enumerate all the types defined in an assembly.
Sub b()
For Each ty As Type In asm.GetTypes
Console.WriteLine(ty.FullName)
Next
End Sub

' Get a reference to a type by its textual name.
Sub c()
Dim ty2 As Type = asm.GetType("System.Data.DataTable")
End Sub

' This statement doesn't raise any exception because type name
' is compared in a case-insensitive way.
Sub d()
Dim ty3 As Type = asm.GetType("system.data.datatable", True, True)
End Sub

End Module

 

18.1.2 AssemblyName

 

代码
Imports System.Reflection

Module Module3
'---------------------------------------------------------
' The AssemblyName Type
'---------------------------------------------------------

Sub a()
' Get a reference to an assembly and its AssemblyName.
Dim asm As Assembly = Assembly.Load("mscorlib")
Dim an As AssemblyName = asm.GetName()

Debug.Assert(an.FullName
= "mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
Debug.Assert(an.ProcessorArchitecture.ToString()
= "X86")

' These properties come from the version object.
Console.WriteLine(an.Version.Major) ' => 2
Console.WriteLine(an.Version.Minor) ' => 0
Console.WriteLine(an.Version.Build) ' => 0
Console.WriteLine(an.Version.Revision) ' => 0

' You can also get the version as a single number.
Debug.Assert(an.Version.ToString() = "2.0.0.0")

' Display the public key token of the assembly
For Each b As Byte In an.GetPublicKeyToken()
Console.Write(
"{0} ", b)
Next

End Sub

' Get information on all the assemblies referenced by the current assembly.
Sub b()
Dim anArr() As AssemblyName
anArr
= Assembly.GetExecutingAssembly.GetReferencedAssemblies()

End Sub

' Create an AssemblyName object from a full name
Sub c()
Dim an2 As New AssemblyName(
"mscorlib, Version=2.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089, ProcessorArchitecture=x86")
End Sub

End Module

 

18.1.3 Module

 

代码
Imports System.Reflection

Module Module4
'---------------------------------------------------------
' The Module Type
'---------------------------------------------------------

' Enumerate all the modules in the mscorlib assembly.
Dim asm As Assembly = Assembly.Load("mscorlib")

Sub a()
' (Note that Module is a reserved word in Visual Basic.)
For Each mo As [Module] In asm.GetModules()
Console.WriteLine(
"{0} - {1}", mo.Name, mo.ScopeName)
Next

Debug.Assert(asm.GetModules().Length
= 1 AndAlso
asm.GetModules()(
0).Name = "mscorlib.dll" AndAlso
asm.GetModules()(
0).ScopeName = "CommonLanguageRuntimeLibrary")
End Sub

' Get a reference to the manifest module
Sub b()
Dim manModule As [Module] = asm.ManifestModule
End Sub

End Module

 18.2 Type

18.2.1 检索Type对象

 

代码
Imports System.Reflection

Module Module5
'---------------------------------------------------------
' Getting a Type Object
'---------------------------------------------------------
Dim asm As Assembly = GetType(Object).Assembly

' List the types in the mscorlib assembly
Sub a()
For Each t As Type In asm.GetTypes()
Console.WriteLine(t.FullName)
Next
End Sub

' Using the GetType VB operator
Sub b()
Dim ty As Type = GetType(String)
Console.WriteLine(ty.FullName)
' => System.String
End Sub

' Using the GetType method
Sub c()
Dim d As Double = 123.45
Dim ty As Type = d.GetType()
Console.WriteLine(ty.FullName)
' => System.Double
End Sub

' Note that you can't pass Type.GetType a Visual Basic synonym,
' such as Short, Integer, Long, or Date.
Sub d()
Dim ty As Type = Type.GetType("System.Int64")
Console.WriteLine(ty.FullName)
' => System.Int64
End Sub

' Using the TYpe.GetType method
Sub e()
Dim typeName As String =
"System.Data.DataSet, System.Data, " &
"Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
Dim ty As Type = Type.GetType(typeName)
End Sub

Sub f()
Dim typeName As String =
"System.String, System.Data, " &
"Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
Dim ty As Type = Type.ReflectionOnlyGetType(typeName, False, False)
End Sub
End Module

 

1. TypeResolve Event

 

代码
Imports System.Reflection
Imports System.IO
Imports System.Runtime.InteropServices

Class TestTypeResolveEvent
Sub TypeResolveEvent()
' Subscribe to the event.
Dim appDom As AppDomain = AppDomain.CurrentDomain
AddHandler appDom.TypeResolve, AddressOf AppDomain_TypeResolve

' Get a reference to the Form type.
' (It should fail, but it doesn't because we are handling the TypeResolve event.)
Dim ty As Type = Type.GetType("System.Windows.Forms.Form")
' Create a form and show it.
Dim obj As Object = ty.InvokeMember(
"", BindingFlags.CreateInstance, Nothing, Nothing, Nothing, Nothing)
ty.InvokeMember(
"Show", BindingFlags.InvokeMethod, Nothing, obj, Nothing)

' Unsubscribe from the event.
RemoveHandler appDom.TypeResolve, AddressOf AppDomain_TypeResolve
End Sub

Private Function AppDomain_TypeResolve(ByVal sender As Object, ByVal e As ResolveEventArgs) As Assembly
If e.Name = "System.Windows.Forms.Form" Then
Dim asmFile As String = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory,
"System.Windows.Forms.dll")
Return Assembly.LoadFile(asmFile)
End If
' Return Nothing if unable to provide an alternative.
Return Nothing
End Function

Sub test()
Dim ty As Type = GetType(Object).Assembly.GetType("System.Windows.Forms.Form")
End Sub
End Class

 

2. 探索Type属性

 

代码
Imports System.Reflection

Module Module6
'---------------------------------------------------------
' Retrieving Type Properties
'---------------------------------------------------------
'All the types exported by mscorlib:
Dim asm As Assembly = Assembly.Load("mscorlib")

Sub a()
For Each t As Type In asm.GetExportedTypes()
If t.IsClass Then
Console.WriteLine(t.Name
& " (Class)")
ElseIf t.IsEnum Then
' An enum is also a value type, so we must test IsEnum before IsValueType.
Console.WriteLine(t.Name & " (Enum)")
ElseIf t.IsValueType Then
Console.WriteLine(t.Name
& " (Structure)")
ElseIf t.IsInterface Then
Console.WriteLine(t.Name
& " (Interface)")
Else
' This statement is never reached because a type
' can't be anything other than one of the above.
End If
Next
End Sub
'Info on all the types exported by mscorlib:
Sub b()
For Each t As Type In asm.GetExportedTypes()
Dim text As String = t.FullName & " "
If t.IsAbstract Then text &= "MustInherit "
If t.IsSealed Then text &= "NotInheritable "
' We need this test because System.Object has no base class.
If t.BaseType IsNot Nothing Then
text
&= "(base: " & t.BaseType.FullName & ") "
End If
Console.WriteLine(text)
Next

End Sub

' Testint type relatonship
Sub c()
Dim obj As Object = New Person()

If TypeOf obj Is Person Then
' obj can be assigned to a Person variable (the VB way).
End If

If GetType(Person).IsAssignableFrom(obj.GetType()) Then
' obj can be assigned to a Person variable (the reflection way).
End If

If GetType(Person).IsInstanceOfType(obj) Then
' obj is a Person object.
End If

If GetType(Person) Is obj.GetType() Then
' obj is a Person object (but fails if obj is Nothing).
End If

If obj.GetType().IsSubclassOf(GetType(Person)) Then
' obj is an object that inherits from Person.
End If
End Sub
End Module

 

3. 枚举成员

 

代码
Imports System.Reflection

Module Module7
'---------------------------------------------------------
' Enumerating Members
'---------------------------------------------------------

'List all the members of the String type:
Sub a()
Dim minfos() As MemberInfo = GetType(String).GetMembers()
For Each mi As MemberInfo In minfos
Console.WriteLine(
"{0} ({1})", mi.Name, mi.MemberType)
Next
End Sub

' Get all public, instance, noninherited members of String type.
Sub b()
Dim minfo() As MemberInfo = GetType(String).GetMembers(
BindingFlags.Public
Or BindingFlags.Instance Or BindingFlags.DeclaredOnly)
End Sub

Sub c(ByVal minfos() As MemberInfo)
For Each mi As MemberInfo In minfos
Console.WriteLine(
"{0} ({1})", mi.Name, mi.MemberType)
Next
End Sub

' All the public methods of the String type
Sub d()
For Each mi As MethodInfo In GetType(String).GetMethods()
Console.WriteLine(mi.Name)
Next
End Sub
' All the interfaces of the String type
Sub e()
For Each itf As Type In GetType(String).GetInterfaces()
Console.WriteLine(itf.FullName)
Next
End Sub

' Get information about the String.Chars property.
Sub f()
Dim pi2 As PropertyInfo = GetType(String).GetProperty("Chars")
Debug.Assert(pi2
IsNot Nothing)
End Sub

' Get the MethodInfo object for the IndexOf string method with the
' following signature: IndexOf(char, startIndex, endIndex).
Sub g()
' Prepare the signature as an array of Type objects.
Dim argTypes() As Type = {GetType(Char), GetType(Integer), GetType(Integer)}

' Ask for the method with given name and signature.
Dim mi2 As MethodInfo = GetType(String).GetMethod("IndexOf", argTypes)
Debug.Assert(mi2
IsNot Nothing)
End Sub

' This code shows how you can build a reference to the following method
' Sub TestMethod(ByRef x As Integer, ByVal arr(,) As String)
Sub h()
Dim argType1 As Type = GetType(Integer).MakeByRefType()
Dim argType2 As Type = GetType(String).MakeArrayType(2)
Dim arrTypes() As Type = {argType1, argType2}
Dim mi3 As MethodInfo = GetType(TestClass).GetMethod("TestMethod", arrTypes)
Debug.Assert(mi3
IsNot Nothing)

End Sub


' Show that array types have a pair of square brackets.
Sub j()
Dim arrTy As Type = GetType(Integer())
Dim arrTy2 As Type = GetType(Integer(,))
Console.WriteLine(arrTy.FullName)
' => System.Int32[]
Console.WriteLine(arrTy2.FullName) ' => System.Int32[,]

Dim vbTypeName As String =
arrTy.FullName.Replace(
"[", "(").Replace("]", ")").Replace("&", "")
End Sub

' Get a reference to the current method
Sub i()
Dim currMethod As MethodBase = MethodBase.GetCurrentMethod()
Debug.Assert(currMethod.Name
= "EnumeratingMembers")
End Sub
End Module

 18.2.2 探讨类型成员

 

代码
' List of members of the String type, suppressing repeated overloaded methods.
Sub ExploringTypeMembers()
' We use this ArrayList to keep track of items already displayed.
Dim al As New ArrayList()
For Each mi As MemberInfo In GetType(String).GetMembers()
If mi.MemberType = MemberTypes.Constructor Then
' Ignore constructor methods.
ElseIf Not mi.DeclaringType Is mi.ReflectedType Then
' Ignore inherited members.
ElseIf Not al.Contains(mi.Name) Then
' If this element hasn't been listed yet, do it now.
Console.WriteLine("{0}({1})", mi.Name, mi.MemberType)

' Add this element to the list of processed items.
al.Add(mi.Name)
End If
Next
End Sub

 

1. 探讨字段

 

代码
' List all the nonconstant fields with Public or Friend scope in the Person type.
Sub ExploringFields1()
For Each fi As FieldInfo In GetType(TestClass).GetFields(BindingFlags.Public Or
BindingFlags.NonPublic
Or BindingFlags.Instance)
If (fi.IsPublic OrElse fi.IsAssembly) AndAlso Not fi.IsLiteral Then
Console.WriteLine(
"{0} As {1}", fi.Name, fi.FieldType.Name)
End If
Next
End Sub

' List all the constants in the Person type.
Sub ExploringFields2()
For Each fi As FieldInfo In GetType(TestClass).GetFields()
If fi.IsLiteral Then
Console.WriteLine(
"{0} = {1}", fi.Name, fi.GetRawConstantValue())
End If
Next
End Sub

 

2.探讨方法

 

代码
' List all methods of the Array class.
Sub ExploringMethods()
For Each mi As MethodInfo In GetType(Array).GetMethods()
' Ignore special methods, such as property getters and setters.
If mi.IsSpecialName Then Continue For
If mi.IsFinal Then
Console.Write(
"NotOverridable ")
ElseIf mi.IsVirtual Then
Console.Write(
"Overridable ")
ElseIf mi.IsAbstract Then
Console.Write(
"MustOverride ")
End If
Dim retTypeName As String = mi.ReturnType.FullName
If retTypeName = "System.Void" Then
Console.WriteLine(
"Sub {0}", mi.Name)
Else
Console.WriteLine(
"Function {0} As {1}", mi.Name, retTypeName)
End If
Next
End Sub

 

3. 探讨属性

 

代码
' Display instance and static Public properties.
Sub ExploringProperties()
For Each pi As PropertyInfo In GetType(TestClass).GetProperties(BindingFlags.Public Or
BindingFlags.Instance
Or BindingFlags.Static)
' Get either the Get or the Set accessor methods.
Dim modifier As String = ""
Dim mi As MethodInfo
If pi.CanRead Then
mi
= pi.GetGetMethod()
If Not pi.CanWrite Then modifier = "ReadOnly "
Else
mi
= pi.GetSetMethod()
modifier
= "WriteOnly "
End If

' Uncomment next line to prove that you can reach the same result
' with the GetAccessors method
' mi = pi.GetAccessors(True)(0)


' Add the Shared qualifier if necessary.
If mi.IsStatic Then modifier = "Shared " & modifier

' Display the Visual Basic syntax.
Console.WriteLine("Public {0}Property {1} As {2}", modifier, pi.Name, pi.PropertyType.FullName)
Next
End Sub

4. 探讨事件

 

代码
Sub ExploringEvents()
' Get information on the SampleEvent event of the TestClass object.
Dim ei As EventInfo = GetType(TestClass).GetEvent("SampleEvent")

' Get a reference to the hidden add_SampleEvent method.
Dim mi2 As MethodInfo = ei.GetAddMethod()

' Test the method scope and check whether it's static.
Console.WriteLine("SampleEvent is static = {0}", mi2.IsStatic)
End Sub

 

5. 探讨参数

 

代码
' Exploring the parameters of a method
Sub ExploringParameters()

Dim mi As MethodInfo = GetType(TestClass).GetMethod("MethodWithOptionalArgs")
Console.Write(mi.Name
& "(")
For Each pi As ParameterInfo In mi.GetParameters()
' Display a comma if it isn't the first parameter.
If pi.Position > 0 Then Console.Write(", ")
If pi.IsOptional Then Console.Write("Optional ")
' Notice how you can discern between ByVal and ByRef parameters.
Dim direction As String = "ByVal"
If pi.ParameterType.IsByRef Then direction = "ByRef"
' Process the parameter type.
Dim tyName As String = pi.ParameterType.FullName
' Convert [] into () and drop the & character (included if parameter is ByRef).
tyName = tyName.Replace("[", "(").Replace("]", ")").Replace("&", "")
Console.Write(
"{0} {1} As {2}", direction, pi.Name, tyName)
' Append the default value for optional parameters.
If pi.IsOptional Then Console.Write(" = " & GetObjectValue(pi.DefaultValue))
Next
Console.WriteLine(
")")
End Sub

' Return the textual representation of an object's value in VB syntax.
Function GetObjectValue(ByVal obj As Object) As String
If obj Is Nothing Then
Return "Nothing"
ElseIf obj.GetType() Is GetType(String) Then
Return """" & obj.ToString() & """"
ElseIf obj.GetType() Is GetType(Date) Then
Return "#" & obj.ToString() & "#"
ElseIf obj.GetType().IsEnum Then
' It's an enum type
Return obj.GetType().Name & "." & [Enum].GetName(obj.GetType(), obj)
Else
' It's something else, including a number.
Return obj.ToString()
End If
End Function

' Exploring the parameters of an event.
Sub ExploringParameters2()
Console.WriteLine(
"The syntax of an event:")
Dim ei As EventInfo = GetType(TestClass).GetEvent("SampleEvent")
Console.Write(ei.Name
& "(")

Dim delegType As Type = ei.EventHandlerType
Dim mi2 As MethodInfo = delegType.GetMethod("Invoke")
For Each pi As ParameterInfo In mi2.GetParameters()
' Display a comma if it isn't the first parameter.
If pi.Position > 0 Then Console.Write(", ")
' Notice how you can discern between ByVal and ByRef parameters.
Dim direction As String = "ByVal"
If pi.ParameterType.IsByRef Then direction = "ByRef"
' Process the parameter type.
Dim tyName As String = pi.ParameterType.FullName
Console.Write(
"{0} {1} As {2}", direction, pi.Name, tyName)
Next
Console.WriteLine(
")")
End Sub

 

6. 探讨方法体

 

代码
Sub ExploringTheMethodBody()
' Get a reference to the method in a type.
Dim mi As MethodInfo = GetType(TestClass).GetMethod("TestMethod")
Dim mb As MethodBody = mi.GetMethodBody()

' Display the number of used stack elements.
Console.WriteLine("Stack Size = {0}", mb.MaxStackSize)

' Display index and type of local variables.
For Each lvi As LocalVariableInfo In mb.LocalVariables
Console.WriteLine(
" var[{0}] As {1}", lvi.LocalIndex, lvi.LocalType.FullName)
Next

' Display information about exception handlers.
For Each ehc As ExceptionHandlingClause In mb.ExceptionHandlingClauses
Console.Write(
" Type={0}, ", ehc.Flags.ToString())
If ehc.Flags = ExceptionHandlingClauseOptions.Clause Then
Console.Write(
"ex As {0}, ", ehc.CatchType.Name)
End If
Console.Write(
"Try offset/length={0}/{1}, ", ehc.TryOffset, ehc.TryLength)
Console.WriteLine(
"Handler offset/length={0}/{1}", ehc.HandlerOffset, ehc.HandlerLength)
Next
End Sub