扩展 Visual Basic 中的
My
Visual Basic 中的命名空间公开属性和方法,使你能够轻松利用 .NET Framework 的强大功能。 命名空间 My
简化了常见的编程问题,通常可将一个难以执行的任务减少到单个代码行。 此外, My
命名空间是完全可扩展的,因此你可以自定义 My
的行为,并在其层次结构中添加新服务,以适应特定的应用程序需求。 本主题讨论如何自定义命名空间的现有成员 My
以及如何将自己的自定义类添加到 My
命名空间。
自定义现有 My
命名空间成员
My
Visual Basic 中的命名空间公开了有关应用程序、计算机等的常用信息。 有关命名空间中 My
对象的完整列表,请参阅 “我的参考”。 可能需要自定义命名空间的现有成员 My
,以便它们更好地满足应用程序的需求。 在 My
命名空间中,任何非只读对象的属性都可以设置为自定义值。
例如,假设你经常使用该 My.User
对象访问运行应用程序的用户的当前安全上下文。 但是,公司使用自定义用户对象公开公司内用户的其他信息和功能。 在此方案中,可以将属性的 My.User.CurrentPrincipal
默认值替换为你自己的自定义主体对象的实例,如以下示例所示:
My.User.CurrentPrincipal = CustomPrincipal
设置 CurrentPrincipal
对象上的 My.User
属性会更改运行应用程序的标识。 该 My.User
对象又返回有关新指定用户的信息。
将成员添加到 My
对象
从My.Application
中返回的类型定义为My.Computer
Partial
类。 因此,你可以通过创建一个名为My.Application
My.Computer
或Partial
的类来扩展MyApplication
和MyComputer
对象。 该类不能是类 Private
。 如果您将类指定为My
命名空间的一部分,您可以添加一些属性和方法,这些属性和方法将包含在My.Application
或My.Computer
对象中。
以下示例将一个名为 DnsServerIPAddresses
对象的属性添加到 My.Computer
该对象:
Imports System.Net.NetworkInformation
Namespace My
Partial Class MyComputer
Friend ReadOnly Property DnsServerIPAddresses() As IPAddressCollection
Get
Dim dnsAddressList As IPAddressCollection = Nothing
For Each adapter In System.Net.NetworkInformation.
NetworkInterface.GetAllNetworkInterfaces()
Dim adapterProperties = adapter.GetIPProperties()
Dim dnsServers As IPAddressCollection = adapterProperties.DnsAddresses
If dnsAddressList Is Nothing Then
dnsAddressList = dnsServers
Else
dnsAddressList.Union(dnsServers)
End If
Next adapter
Return dnsAddressList
End Get
End Property
End Class
End Namespace
将自定义对象添加到 My
命名空间
尽管命名空间 My
为许多常见编程任务提供了解决方案,但可能会遇到命名空间无法解决的任务 My
。 例如,应用程序可能会访问用户数据的自定义目录服务,或者应用程序可能使用默认情况下未随 Visual Basic 一起安装的程序集。 可以扩展 My
命名空间,以包含特定于环境的常见任务的自定义解决方案。
My
可以轻松扩展命名空间,以添加新成员以满足不断增长的应用程序需求。 此外,您还可以将您的My
命名空间扩展作为 Visual Basic 模板部署给其他开发人员。
将成员添加到 My
命名空间
由于My
是一个与其他命名空间类似的命名空间,您只需添加模块并指定Namespace
My
即可为其添加顶级属性。 使用 HideModuleName
属性批注模块,如以下示例所示。 该 HideModuleName
属性可确保 IntelliSense 在显示命名空间的成员 My
时不会显示模块名称。
Namespace My
<HideModuleName()>
Module MyCustomModule
End Module
End Namespace
若要将成员添加到 My
命名空间,请根据需要向模块添加属性。 对于添加到 My
命名空间的每个属性,请添加一个类型 ThreadSafeObjectProvider(Of T)
专用字段,其中类型是自定义属性返回的类型。 此字段用于通过调用 GetInstance
方法创建属性返回的线程安全对象实例。 因此,访问扩展属性的每个线程都会收到其自己的返回类型的实例。 以下示例向命名空间SampleExtension
添加一个名为SampleExtension
的属性,其类型为My
。
Namespace My
<HideModuleName()>
Module MyCustomExtensions
Private _extension As New ThreadSafeObjectProvider(Of SampleExtension)
Friend ReadOnly Property SampleExtension() As SampleExtension
Get
Return _extension.GetInstance()
End Get
End Property
End Module
End Namespace
将事件添加到自定义 My
对象
可以通过扩展My.Application
命名空间中的My
分部类,使用该MyApplication
对象来公开自定义My
对象的事件。 对于基于 Windows 的项目,可以在解决方案资源管理器中为项目双击“我的项目”节点。 在 Visual Basic 项目设计器中,单击 “应用程序 ”选项卡,然后单击“ 查看应用程序事件 ”按钮。 将创建一个名为 ApplicationEvents.vb 的新文件。 它包含用于扩展 MyApplication
类的以下代码:
Namespace My
Partial Friend Class MyApplication
End Class
End Namespace
可以通过向My
类添加自定义事件处理程序来为自定义MyApplication
对象添加事件处理程序。 通过自定义事件,可以在添加事件处理程序、删除事件处理程序或引发事件时,执行相关的代码。 请注意, AddHandler
仅当用户添加代码来处理该事件时,自定义事件的代码才会运行。 例如,请考虑上一节中的SampleExtension
对象具有一个Load
事件,您希望为此添加一个自定义事件处理程序。 下面的代码示例展示了一个自定义事件处理程序,名为SampleExtensionLoad
,它将在My.SampleExtension.Load
事件发生时被调用。 添加代码来处理新 My.SampleExtensionLoad
事件时, AddHandler
将执行此自定义事件代码的一部分。 该方法 MyApplication_SampleExtensionLoad
包含在代码示例中,用于显示处理事件的 My.SampleExtensionLoad
事件处理程序示例。 请注意,SampleExtensionLoad
编辑ApplicationEvents.vb文件时,在代码编辑器上方的左侧下拉列表中选择“我的应用程序事件”选项时,该事件将可用。
Namespace My
Partial Friend Class MyApplication
' Custom event handler for Load event.
Private _sampleExtensionHandlers As EventHandler
Public Custom Event SampleExtensionLoad As EventHandler
AddHandler(ByVal value As EventHandler)
' Warning: This code is not thread-safe. Do not call
' this code from multiple concurrent threads.
If _sampleExtensionHandlers Is Nothing Then
AddHandler My.SampleExtension.Load, AddressOf OnSampleExtensionLoad
End If
_sampleExtensionHandlers =
System.Delegate.Combine(_sampleExtensionHandlers, value)
End AddHandler
RemoveHandler(ByVal value As EventHandler)
_sampleExtensionHandlers =
System.Delegate.Remove(_sampleExtensionHandlers, value)
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
If _sampleExtensionHandlers IsNot Nothing Then
_sampleExtensionHandlers.Invoke(sender, e)
End If
End RaiseEvent
End Event
' Method called by custom event handler to raise user-defined
' event handlers.
<Global.System.ComponentModel.EditorBrowsable(
Global.System.ComponentModel.EditorBrowsableState.Advanced)>
Protected Overridable Sub OnSampleExtensionLoad(
ByVal sender As Object, ByVal e As EventArgs)
RaiseEvent SampleExtensionLoad(sender, e)
End Sub
' Event handler to call My.SampleExtensionLoad event.
Private Sub MyApplication_SampleExtensionLoad(
ByVal sender As Object, ByVal e As System.EventArgs
) Handles Me.SampleExtensionLoad
End Sub
End Class
End Namespace
设计指南
开发命名空间的 My
扩展时,请使用以下准则来帮助最大程度地降低扩展组件的维护成本:
- 仅包含扩展逻辑。 命名空间扩展中包含的
My
逻辑应仅包含公开命名空间中My
所需功能所需的代码。 由于扩展将作为源代码驻留在用户项目中,因此更新扩展组件会产生较高的维护成本,如果可能,应避免这样做。 - 最小化项目假设。 在创建您自己的
My
命名空间扩展时,请不要假设有一组引用、项目级导入或特定的编译器设置(例如Option Strict
禁用)。 而是使用Global
关键字最大程度地减少依赖项并完全限定所有类型引用。 此外,请确保在打开Option Strict
的情况下编译扩展,以最大程度地减少扩展中的错误。 - 隔离扩展代码。 将代码放置在单个文件中可使扩展轻松部署为 Visual Studio 项模板。 有关详细信息,请参阅本主题后面的“打包和部署扩展”。 将所有
My
命名空间扩展代码放在单个文件或项目中的单独文件夹中也有助于用户找到My
命名空间扩展。
为 My
设计类库
与大多数对象模型一样,一些设计模式在命名空间中 My
效果良好,其他模式则不起作用。 设计命名空间的 My
扩展时,请考虑以下原则:
- 无状态方法。 命名空间中的
My
方法应为特定任务提供完整的解决方案。 确保传递给方法的参数值提供完成特定任务所需的所有输入。 避免创建依赖于先前状态的方法,例如打开与资源的连接。 - 全局实例。 命名空间
My
中唯一被维护的状态是针对整个项目的全局状态。 例如,My.Application.Info
封装了在整个应用程序中共享的状态。 - 简单参数类型。 通过避免复杂的参数类型来简化处理。 而是创建不采用参数输入或采用简单输入类型(如字符串、基元类型等)的方法。
- 工厂方法。 某些类型一定难以实例化。 提供工厂方法作为
My
命名空间的扩展,这样一来,你可以更轻松地发现和使用属于此类别的类型。 运行良好的工厂方法的一个示例是My.Computer.FileSystem.OpenTextFileReader
。 .NET Framework 中提供了多种流类型。 通过专门指定文本文件,OpenTextFileReader
帮助用户了解要使用的流。
这些准则不排除类库的一般设计原则。 而是针对使用 Visual Basic 和命名空间的 My
开发人员优化的建议。 有关创建类库的常规设计原则,请参阅 框架设计指南。
打包和部署扩展
可以在 My
Visual Studio 项目模板中包含命名空间扩展,也可以打包扩展并将其部署为 Visual Studio 项模板。 将My
命名空间扩展打包为 Visual Studio 项目模板时,可以利用 Visual Basic 提供的其他功能。 这些功能使你可以在项目引用特定程序集时包括扩展,或者允许用户使用 Visual Basic 项目设计器的My
”页显式添加命名空间扩展。
有关如何部署 My
命名空间扩展的详细信息,请参阅 打包和部署自定义我的扩展。