1. Trang chủ
  2. » Công Nghệ Thông Tin

Visual Basic 2005 Design and Development - Chapter 22 docx

26 296 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 26
Dung lượng 823,25 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The code then adds a node labeled Referenced Assembliesto the tree view.. The code adds the assembly’s entry point to the tree view, and then loops through the exported publictypes defin

Trang 1

Even if you don’t expect your program to interact with other assemblies, you may find somereflection techniques useful For example, if your application uses only its own modules, you maynot think you need to use reflection to learn about what is contained in those modules After all,you are writing the code, so you should know what it contains

However, it may still be useful for the program to load assemblies at run-time For example, theprogram can look in a tools directory to see what assemblies are available and load any tools thatthey define Then, if you later decide to add, modify, or remove a tool, you only need to add,replace, or remove an assembly from this directory, and the program will automatically updateitself the next time it runs That makes distributing new tools to users quick and easy

There isn’t enough room in this chapter to cover all of the reflection tools provided by the NETFramework, but there is enough room to cover some of the most useful of those tools That shouldgive you enough of a start that you can figure out how to use other tools as needed

Exploring Assemblies

An obvious first task when using reflection is learning information about an assembly

An assembly is the smallest unit of deployment in a NET application It is basically a piece of compiled code Generally, that means a compiled .exeor .dllfile.

Trang 2

Example program GetAssemblyInformation(available for download at www.vb-helper.com/one_on_one.htm) displays information about an assembly stored in a file It’s a long and involved program,but its basic operations are relatively simple when taken individually The program doesn’t even try todisplay all of the possible information about the assembly Instead, it sticks to the most common anduseful bits of information.

When you enter the path to an assembly and click the Go button, the program executes the followingcode:

‘ Display information about the assembly

Private Sub btnGo_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles btnGo.Click

Dim assem As [Assembly] = [Assembly].LoadFrom(txtPath.Text)

‘ Display the assembly’s full name

trvDetails.Nodes.Clear()trvDetails.Nodes.Add(“Full Name: “ & assem.FullName)trvDetails.Nodes.Add(“Location: “ & assem.Location)

‘ Display referenced assemblies

Dim ref_assem_node As TreeNode = trvDetails.Nodes.Add(“Referenced Assemblies”)For Each referenced_assembly As AssemblyName In assem.GetReferencedAssemblies()ref_assem_node.Nodes.Add(referenced_assembly.FullName)

Next referenced_assembly

‘ Display the assembly’s entry point

Dim entry_point As MethodInfo = assem.EntryPoint()trvDetails.Nodes.Add(“Entry Point: “ & entry_point.Name)

‘ Types

Dim types_node As TreeNode = trvDetails.Nodes.Add(“Types”)For Each exported_type As Type In assem.GetTypes()

AddTypeData(types_node, exported_type)Next exported_type

End Sub

First, the code creates an Assemblyobject based on the assembly file you entered in the txtPathtextbox It then clears the trvDetails TreeViewcontrol, where it will store its results, and adds the assem-bly’s full name (name, version, culture, and token) and its location to the tree view

The code then adds a node labeled Referenced Assembliesto the tree view It loops through the ues in the assemblies returned by the Assemblyobject’s GetReferencedAssembliesfunction, addingeach assembly’s name to the tree view

val-This code shows a common operation when exploring an assembly: the code finds an object and loops

through an array representing items that are logically contained in the original object In this case, the

Assemblyobject provides a list of referenced assemblies Similarly, a Typeobject representing a class can have properties, fields, methods, events, and nested types.

The code adds the assembly’s entry point to the tree view, and then loops through the exported (public)types defined by the assembly For each of these types, the code calls subroutine AddTypeDatato addinformation about the type to the tree view The following code shows subroutine AddTypeData:

Trang 3

‘ Return information about a type.

Private Sub AddTypeData(ByVal parent_node As TreeNode, ByVal the_type As Type)Dim txt As String = “”

If the_type.IsPublic Then txt &= “Public “

If the_type.IsInterface Then

‘ Skip MustInherit for Interfaces

txt &= “Interface “Else

If the_type.IsAbstract Then txt &= “MustInherit “End If

If the_type.IsClass Then txt &= “Class “

If the_type.IsEnum Then txt &= “Enum “

If the_type.IsValueType Then txt &= “Structure “

Dim type_name As String = the_type.Name

If the_type.ContainsGenericParameters Then

‘ Remove whatever comes after `

type_name = type_name.Substring(0, type_name.IndexOf(“`”))

‘ Compose the generic parameters

Dim generic_params As String = “”

Dim generic_type As Type = the_type.GetGenericTypeDefinitionFor Each arg_type As Type In generic_type.GetGenericArguments()generic_params &= “, “ & arg_type.Name

Next arg_type

If generic_params.Length > 0 Then _generic_params = generic_params.Substring(2)type_name &= “(Of “ & generic_params & “)”

End IfDim type_node As TreeNode = parent_node.Nodes.Add(txt & type_name)

If the_type.BaseType Is Nothing Thentype_node.Nodes.Add(“Inherits From: Nothing”)Else

type_node.Nodes.Add(“Inherits From: “ & the_type.BaseType.FullName)End If

type_node.Nodes.Add(“Attributes: “ & the_type.Attributes.ToString)type_node.Nodes.Add(“Qualified Name: “ & the_type.AssemblyQualifiedName)

‘ See if it’s an enum

If the_type.IsEnum Then

‘ It’s an enum List its values

Dim values_node As TreeNode = type_node.Nodes.Add(“Values”)For Each field_info As FieldInfo In the_type.GetFields()

If field_info.IsStatic Thenvalues_node.Nodes.Add(field_info.Name & “ = “ & _CLng(field_info.GetValue(Nothing)))

Elsevalues_node.Nodes.Add(field_info.Name & “ (non static)”)End If

Next field_infoElse

‘ It’s not an enum

‘ Interfaces

Dim ifaces() As Type = the_type.GetInterfaces()

Trang 4

If ifaces.Length > 0 ThenDim ifaces_node As TreeNode = type_node.Nodes.Add(“Interfaces”)For Each iface_type As Type In ifaces

AddInterfaceData(ifaces_node, iface_type)Next iface_type

End If

‘ Constructors

Dim constructor_infos() As ConstructorInfo = the_type.GetConstructors()

‘ If constructor_infos = Nothing,

‘ the type has only a default constructor

‘ If constructor_infos is empty, it has no constructors

If constructor_infos Is Nothing Then

‘ It has no explicit constructors,

‘ only the default empty constructor

Dim constr_node As TreeNode = type_node.Nodes.Add(“Constructors”)constr_node.Nodes.Add(“New “ & type_name & “()”)

ElseIf constructor_infos.Length > 0 ThenDim constr_node As TreeNode = type_node.Nodes.Add(“Constructors”)For Each constructor_info As ConstructorInfo In constructor_infosAddConstructorData(constr_node, type_name, constructor_info)Next constructor_info

End If

‘ Fields

Dim field_infos() As FieldInfo = the_type.GetFields()

If field_infos.Length > 0 ThenDim fields_node As TreeNode = type_node.Nodes.Add(“Fields”)For Each field_info As FieldInfo In field_infos

AddFieldData(fields_node, field_info)Next field_info

End If

‘ Properties

Dim property_infos() As PropertyInfo = the_type.GetProperties()

If property_infos.Length > 0 ThenDim properties_node As TreeNode = type_node.Nodes.Add(“Properties”)For Each property_info As PropertyInfo In property_infos

AddPropertyData(properties_node, property_info)Next property_info

End If

‘ Methods

Dim method_infos() As MethodInfo = the_type.GetMethods()

If method_infos.Length > 0 ThenDim methods_node As TreeNode = type_node.Nodes.Add(“Methods”)For Each method_info As MethodInfo In method_infos

AddMethodData(methods_node, method_info)Next method_info

End If

‘ Events

Dim event_infos() As EventInfo = the_type.GetEvents()

If event_infos.Length > 0 Then

Trang 5

Dim events_node As TreeNode = type_node.Nodes.Add(“Events”)For Each event_info As EventInfo In event_infos

AddEventData(events_node, event_info)Next event_info

End If

‘ Nested types

Dim nested_types() As Type = the_type.GetNestedTypes()

If nested_types.Length > 0 ThenDim nested_types_node As TreeNode = type_node.Nodes.Add(“Nested Types”)For Each nested_type As Type In nested_types

AddTypeData(nested_types_node, nested_type)Next nested_type

End IfEnd IfEnd Sub

Subroutine AddTypeDatatakes a Typeobject as a parameter It checks the Type’s properties to mine whether the type is public, an interface, MustInherit, a class, an enumerated type, or a structure

deter-It uses this information to build an appropriate declaration string for the type

Next, the routine checks whether the type contains generic parameters, as in Public ClassTestClass(Of T1, T2) If it does, the code loops through the generic arguments to build an appropri-ate parameter list

The code then adds a node to the tree view containing the type’s basic declaration The code adds anyother tree view nodes for this type as descendants of this node

The subroutine adds entries, giving the type from which this one inherits (note that interfaces don’tinherit from anything), its attributes, and its fully qualified name It then considers other items that arelogically contained within the type

If the type is an Enum, the code loops through its fields If a field is static (has a constant value), the codedisplays its name and its value If a field is not static, the code displays the field’s name

If the type is not an Enum, the subroutine loops through and displays information about the interfaces itimplements It then describes the type’s constructors, fields, properties, methods, events, and nestedtypes (for example, classes defined within this class)

For each of these more-complicated items, the AddTypeDatasubroutine calls other routines to provideadditional information For example, for a constructor, it calls subroutine AddConstructorData For anested type, subroutine AddTypeDatacalls itself recursively to describe the nested type

The other routines used by the program are much simpler Subroutine AddConstructorDatashown inthe following code adds a node to the tree view describing a constructor It starts with the keyword New

and uses function ParameterListto list its parameters

‘ Return information about a type

Private Sub AddConstructorData(ByVal parent_node As TreeNode, _ByVal type_name As String, ByVal constructor_info As ConstructorInfo)

‘ Get the constructor’s parameters

Dim txt As String = “New “ & type_name & _

Trang 6

End Sub

Function ParameterListloops through an array of ParameterInfoobjects and calls GetParameterDatato get a declaration for each

‘ Return a string listing parameters from a collection

Private Function ParameterList(ByVal param_infos() As ParameterInfo) As StringDim params As String = “”

For Each parameter_info As ParameterInfo In param_infosparams &= “, “ & GetParameterData(parameter_info)Next parameter_info

If params.Length > 0 Then params = params.Substring(2)

Return “(“ & params & “)”

End Function

Function GetParameterDataexamines a ParameterInfoobject and builds its declaration as it wouldappear within a parameter list This function is somewhat limited For example, it doesn’t try to com-pletely interpret parameters that are of generic types as in Sub Test(ByVal values As List(OfBoolean))

‘ Return information about a parameter

Private Function GetParameterData(ByVal parameter_info As ParameterInfo) As StringDim txt As String = “”

If parameter_info.IsOptional Thentxt &= “Optional “

End If

If parameter_info.IsOut Thentxt &= “ByRef “

Elsetxt &= “ByVal “End If

txt &= parameter_info.Name

If parameter_info.ParameterType.IsArray Thentxt &= “()”

txt &= “ As “ & parameter_info.ParameterType.GetElementType.NameElse

txt &= “ As “ & parameter_info.ParameterType.NameEnd If

End If

Return txtEnd Function

Trang 7

Subroutines AddFieldDataand AddPropertyData, shown in the following code, examine FieldInfo

and PropertyInfoobjects to provide reasonable declarations for fields (public variables) and properties

‘ Add information about a field

Private Sub AddFieldData(ByVal fields_node As TreeNode, _ByVal field_info As FieldInfo)

Dim txt As String = “”

If field_info.IsPublic Then txt &= “Public “

If field_info.IsPrivate Then txt &= “Private “

If field_info.IsFamily Then txt &= “Protected “

If field_info.IsStatic Then txt &= “Shared “txt &= field_info.Name

txt &= “ As “ & field_info.FieldType.Namefields_node.Nodes.Add(txt)

End Sub

‘ Add information about a property

Private Sub AddPropertyData(ByVal properties_node As TreeNode, _ByVal property_info As PropertyInfo)

Dim txt As String = “Public “

If property_info.CanRead AndAlso Not property_info.CanWrite Thentxt &= “ReadOnly “

ElseIf Not property_info.CanRead AndAlso property_info.CanWrite Thentxt &= “WriteOnly “

End Iftxt &= property_info.Nametxt &= “ As “ & property_info.PropertyType.Nameproperties_node.Nodes.Add(txt)

‘ Add information about a method

Private Sub AddMethodData(ByVal methods_node As TreeNode, _ByVal method_info As MethodInfo)

methods_node.Nodes.Add(MethodSignature(method_info))End Sub

‘ Return a method’s signature in a VB format

Private Function MethodSignature(ByVal method_info As MethodInfo) As StringDim txt As String = “”

If method_info.IsFamilyAndAssembly Thentxt &= “Protected Friend “

ElseIf method_info.IsFamily Thentxt &= “Protected “

ElseIf method_info.IsFamilyOrAssembly Thentxt &= “Friend “

ElseIf method_info.IsPrivate Thentxt &= “Private “

ElseIf method_info.IsPublic Then

Trang 8

txt &= “Public “End If

If method_info.IsFinal Then txt &= “NotOverridable “

If method_info.IsHideBySig Then txt &= “Overrides “

If method_info.IsAbstract Then txt &= “MustOverride “

If method_info.IsStatic Then txt &= “Shared “

If method_info.ReturnType.Name = “Void” Thentxt &= “Sub “

Elsetxt &= “Function “End If

txt &= method_info.Nametxt &= ParameterList(method_info.GetParameters())

If method_info.ReturnType.Name <> “Void” Thentxt &= “ As “ & method_info.ReturnType.NameEnd If

Return txtEnd Function

Subroutine AddEventDatasimply adds an event’s name to the tree view, and subroutine

AddInterfaceDatajust adds the keyword Implementsand the interface’s name to the output

‘ Add information about an event

Private Sub AddEventData(ByVal events_node As TreeNode, _

ByVal event_info As EventInfo)

events_node.Nodes.Add(event_info.Name)End Sub

‘ Add information about an implemented interface

Private Sub AddInterfaceData(ByVal ifaces_node As TreeNode, _

ByVal iface_type As Type)

ifaces_node.Nodes.Add(“Implements “ & iface_type.Name)End Sub

Figure 22-1 shows program GetAssemblyInformationin action In this figure, the Employeeclass isopen and displaying its interfaces, constructors, fields, and properties

You can download the example program at www.vb-helper.com/one_on_one.htmand look at the

Employeeclass it defines to see how it leads to the results shown in Figure 22-1

Example program GetMyAssemblyInformationis almost the same as program

GetAssemblyInformation, except it doesn’t load an Assemblyobject from a file Instead this programuses the following statement to get an Assemblyrepresenting itself as it is running:

Dim assem As [Assembly] = [Assembly].GetExecutingAssembly()

This is reflection in a fairly literal sense The code is actually examining at itself as if it were looking in

a mirror.

Trang 9

Figure 22-1: Program GetAssemblyInformationdisplays information about anassembly.

You may find program GetAssemblyInformationuseful for exploring assemblies, but it’s more important

as an example showing how you can search through an assembly for particular information For example, itshows how you can search an assembly to find the classes it defines It also shows how to examine thoseclasses to see which ones provide default constructors that take no parameters Your program can easilymake instances of those classes and possibly use their methods Example programs UseReflectionTools

and UseDiscoveryLib(described later in this chapter) demonstrate this technique

Exploring EnumerationsThe NET Framework includes many enumerations, including some that are very large such as

HatchStylewith 56 entries and Colorwith 141 entries Suppose you are building a drawing programand you want to let the user pick from among these values

Building the lists of HatchStylesand Colorswould be a lot of work It would also make maintenancemore difficult If a later release of the NET Framework defined new colors, for example, you wouldhave to figure out which ones were new and add them to your list

An alternative solution is to use reflection to make the HatchStyleand Colortypes list their own values.Example program ShowHatchBrushes(available for download at www.vb-helper.com/one_on_one.htm) uses the following code to show samples of the defined HatchStylevalues:

‘ Display brush samples

Private Sub Form1_Paint(ByVal sender As Object, _

Trang 10

ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint

e.Graphics.Clear(Me.BackColor)Dim x As Integer = XMINDim y As Integer = XMIN

‘ Enumerate the HatchBrush styles

Dim hatch_style_type As Type = GetType(HatchStyle)

Dim field_infos() As FieldInfo = hatch_style_type.GetFields()For Each field_info As FieldInfo In field_infos

‘ See if this is a static (Shared) property

‘ We only want the Shared properties such as Horizontal

‘ and not the instance properties such as value

If field_info.IsStatic Then

‘ Get this brush

Dim style_obj As Object = field_info.GetValue(Nothing)Dim hatch_style As HatchStyle = DirectCast(style_obj, HatchStyle)

‘ Make the brush and draw the sample

Using br As New HatchBrush(hatch_style, Color.Black, Color.White)DrawSample(e.Graphics, x, y, br, field_info.Name)

End UsingEnd IfNext field_infoEnd Sub

‘ Draw the sample and move (x, y) to a new position

Private Sub DrawSample(ByVal gr As Graphics, ByRef x As Integer, _

ByRef y As Integer, ByVal br As Brush, ByVal brush_name As String)

‘ Draw the sample

gr.FillRectangle(br, x, y, SAMPLE_WID, SAMPLE_HGT)gr.DrawRectangle(Pens.Red, x, y, SAMPLE_WID, SAMPLE_HGT)

‘ Draw the brush’s name

Dim string_format As New StringFormat()string_format.Alignment = StringAlignment.Centerstring_format.LineAlignment = StringAlignment.Neargr.DrawString(brush_name, Me.Font, Brushes.Blue, _

x + SAMPLE_WID \ 2, y + SAMPLE_HGT, string_format)

End Sub

The form’s Paintevent handler gets a Typeobject representing the HatchStyletype It then loopsthrough the FieldInfoobjects representing the type’s fields It uses each FieldInfo’s IsStatic

method to determine whether a field is a constant, and calls subroutine DrawSampleto draw a sample

of the static fields

Trang 11

Subroutine DrawSamplefills a rectangle with the sample brush, draws a rectangle around it, and plays the style’s name underneath It then updates the X and Y coordinates where it will draw the nextsample.

dis-Figure 22-2 shows program ShowHatchBrushesdisplaying the hatch styles defined by the HatchStyle

‘ Enumerate the SystemColors styles

Dim system_colors_type As Type = GetType(SystemColors)Dim property_infos() As PropertyInfo = system_colors_type.GetProperties()For Each property_info As PropertyInfo In property_infos

‘ Get this color

Dim color_obj As Object = property_info.GetValue(Nothing, Nothing)Dim system_color As Color = DirectCast(color_obj, Color)

‘ Save the color and name

Trang 12

m_Colors.Add(system_color)m_ColorNames.Add(property_info.Name)Next property_info

‘ Prepare for Paint events

Me.SetStyle( _ControlStyles.AllPaintingInWmPaint Or _ControlStyles.ResizeRedraw Or _

ControlStyles.OptimizedDoubleBuffer, _True)

Me.UpdateStyles()

Me.ClientSize = New Size( _

2 * XMIN + 6 * SAMPLE_WID + 5 * X_MARGIN, _

3 * XMIN + 6 * SAMPLE_HGT + 5 * Y_MARGIN)End Sub

The form’s Paintevent handler draws samples of the colors in the m_Colorsarray Download the code

to see the details

Figure 22-3 shows program ShowSystemColorsin action

Figure 22-3: Program ShowSystemColorsdraws samples of the values defined by

Trang 13

Program Enumeration

ShowSystemColors SystemColorsShowSystemIcons SystemIcons

Loading Classes DynamicallyChapter 9, “Scripting,” explains some ways you can add new functionality to an application In particu-lar it explains how you can make an application compile and execute new Visual Basic code at run-time.Using this technique, you can add new features to a previously compiled application

Chapter 18, “Deployment,” discusses different methods that you can use to deploy an application If youdon’t change a method’s signature, you may be able to change its behavior to provide new features for

an existing application For example, suppose you build a class library that defines a Toolsclass Thisclass provides an InstallToolsmethod that adds new items to the main program’s menus and han-dles the new items’ Clickevents If you are careful, you can change the way InstallToolsworks andcopy a new DLL into the program’s directory without breaking the application

Reflection gives you another option for loading and executing new code Instead of compiling new code

at run-time or relying on the classes in a DLL not changing in significant ways, a program can use tion to open an assembly, find useful classes in it, and use them

reflec-The ReflectionToolsexample project (available for download at www.vb-helper.com/one_on_one.htm) builds a DLL that contains classes that provide tools for another application The followingcode shows how the library installs tools:

Imports System.Windows.FormsImports System.Drawing

‘ Identifies the tool installer class

Public Interface IToolInstallerSub InstallTools(ByVal tool_menu As ToolStripMenuItem, _ByVal rch As RichTextBox)

End Interface

‘ Lists the available tool classes

Public Class ToolInstallerImplements IToolInstaller

‘ Install tools for this application

Public Sub InstallTools(ByVal tool_menu As ToolStripMenuItem, _ByVal rch As System.Windows.Forms.RichTextBox) _

Implements IToolInstaller.InstallToolsDim bold_toggler As New BoldStyleTogglerbold_toggler.InstallTool(tool_menu, rch)End Sub

End Class

Ngày đăng: 14/08/2014, 11:20

TỪ KHÓA LIÊN QUAN