扩展 Visual Basic 中的 My 命名空间

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.ComputerPartial类。 因此,你可以通过创建一个名为My.ApplicationMy.ComputerPartial的类来扩展MyApplicationMyComputer对象。 该类不能是类 Private 。 如果您将类指定为My命名空间的一部分,您可以添加一些属性和方法,这些属性和方法将包含在My.ApplicationMy.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是一个与其他命名空间类似的命名空间,您只需添加模块并指定NamespaceMy即可为其添加顶级属性。 使用 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 命名空间扩展的详细信息,请参阅 打包和部署自定义我的扩展

另请参阅