Extending the My
Namespace in Visual Basic
The My
namespace in Visual Basic exposes properties and methods that enable you to easily take advantage of the power of the .NET Framework. The My
namespace simplifies common programming problems, often reducing a difficult task to a single line of code. Additionally, the My
namespace is fully extensible so that you can customize the behavior of My
and add new services to its hierarchy to adapt to specific application needs. This topic discusses both how to customize existing members of the My
namespace and how to add your own custom classes to the My
namespace.
Customizing existing My
namespace members
The My
namespace in Visual Basic exposes frequently used information about your application, your computer, and more. For a complete list of the objects in the My
namespace, see My Reference. You may have to customize existing members of the My
namespace so that they better match the needs of your application. Any property of an object in the My
namespace that is not read-only can be set to a custom value.
For example, assume that you frequently use the My.User
object to access the current security context for the user running your application. However, your company uses a custom user object to expose additional information and capabilities for users within the company. In this scenario, you can replace the default value of the My.User.CurrentPrincipal
property with an instance of your own custom principal object, as shown in the following example:
My.User.CurrentPrincipal = CustomPrincipal
Setting the CurrentPrincipal
property on the My.User
object changes the identity under which the application runs. The My.User
object, in turn, returns information about the newly specified user.
Adding members to My
objects
The types returned from My.Application
and My.Computer
are defined as Partial
classes. Therefore, you can extend the My.Application
and My.Computer
objects by creating a Partial
class named MyApplication
or MyComputer
. The class cannot be a Private
class. If you specify the class as part of the My
namespace, you can add properties and methods that will be included with the My.Application
or My.Computer
objects.
The following example adds a property named DnsServerIPAddresses
to the My.Computer
object:
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
Adding custom objects to the My
namespace
Although the My
namespace provides solutions for many common programming tasks, you may encounter tasks that the My
namespace does not address. For example, your application might access custom directory services for user data, or your application might use assemblies that are not installed by default with Visual Basic. You can extend the My
namespace to include custom solutions to common tasks that are specific to your environment. The My
namespace can easily be extended to add new members to meet growing application needs. Additionally, you can deploy your My
namespace extensions to other developers as a Visual Basic template.
Adding members to the My
namespace
Because My
is a namespace like any other namespace, you can add top-level properties to it by just adding a module and specifying a Namespace
of My
. Annotate the module with the HideModuleName
attribute as shown in the following example. The HideModuleName
attribute ensures that IntelliSense will not display the module name when it displays the members of the My
namespace.
Namespace My
<HideModuleName()>
Module MyCustomModule
End Module
End Namespace
To add members to the My
namespace, add properties as needed to the module. For each property added to the My
namespace, add a private field of type ThreadSafeObjectProvider(Of T)
, where the type is the type returned by your custom property. This field is used to create thread-safe object instances to be returned by the property by calling the GetInstance
method. As a result, each thread that is accessing the extended property receives its own instance of the returned type. The following example adds a property named SampleExtension
that is of type SampleExtension
to the My
namespace:
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
Adding events to custom My
objects
You can use the My.Application
object to expose events for your custom My
objects by extending the MyApplication
partial class in the My
namespace. For Windows-based projects, you can double-click the My Project node in for your project in Solution Explorer. In the Visual Basic Project Designer, click the Application tab and then click the View Application Events button. A new file that is named ApplicationEvents.vb will be created. It contains the following code for extending the MyApplication
class:
Namespace My
Partial Friend Class MyApplication
End Class
End Namespace
You can add event handlers for your custom My
objects by adding custom event handlers to the MyApplication
class. Custom events enable you to add code that will execute when an event handler is added, removed, or the event is raised. Note that the AddHandler
code for a custom event runs only if code is added by a user to handle the event. For example, consider that the SampleExtension
object from the previous section has a Load
event that you want to add a custom event handler for. The following code example shows a custom event handler named SampleExtensionLoad
that will be invoked when the My.SampleExtension.Load
event occurs. When code is added to handle the new My.SampleExtensionLoad
event, the AddHandler
part of this custom event code is executed. The MyApplication_SampleExtensionLoad
method is included in the code example to show an example of an event handler that handles the My.SampleExtensionLoad
event. Note that the SampleExtensionLoad
event will be available when you select the My Application Events option in the left drop-down list above the Code Editor when you are editing the ApplicationEvents.vb file.
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
Design guidelines
When you develop extensions to the My
namespace, use the following guidelines to help minimize the maintenance costs of your extension components:
- Include only the extension logic. The logic included in the
My
namespace extension should include only the code that is needed to expose the required functionality in theMy
namespace. Because your extension will reside in user projects as source code, updating the extension component incurs a high maintenance cost and should be avoided if possible. - Minimize project assumptions. When you create your extensions of the
My
namespace, do not assume a set of references, project-level imports, or specific compiler settings (for example,Option Strict
off). Instead, minimize dependencies and fully qualify all type references by using theGlobal
keyword. Also, ensure that the extension compiles withOption Strict
on to minimize errors in the extension. - Isolate the extension code. Placing the code in a single file makes your extension easily deployable as a Visual Studio item template. For more information, see "Packaging and Deploying Extensions" later in this topic. Placing all the
My
namespace extension code in a single file or a separate folder in a project will also help users locate theMy
namespace extension.
Designing class libraries for My
As is the case with most object models, some design patterns work well in the My
namespace and others do not. When designing an extension to the My
namespace, consider the following principles:
- Stateless methods. Methods in the
My
namespace should provide a complete solution to a specific task. Ensure that the parameter values that are passed to the method provide all the input required to complete the particular task. Avoid creating methods that rely on prior state, such as open connections to resources. - Global instances. The only state that is maintained in the
My
namespace is global to the project. For example,My.Application.Info
encapsulates state that is shared throughout the application. - Simple parameter types. Keep things simple by avoiding complex parameter types. Instead, create methods that either take no parameter input or that take simple input types such as strings, primitive types, and so on.
- Factory methods. Some types are necessarily difficult to instantiate. Providing factory methods as extensions to the
My
namespace enables you to more easily discover and consume types that fall into this category. An example of a factory method that works well isMy.Computer.FileSystem.OpenTextFileReader
. There are several stream types available in the .NET Framework. By specifying text files specifically, theOpenTextFileReader
helps the user understand which stream to use.
These guidelines do not preclude general design principles for class libraries. Rather, they are recommendations that are optimized for developers who are using Visual Basic and the My
namespace. For general design principles for creating class libraries, see Framework Design Guidelines.
Packaging and deploying extensions
You can include My
namespace extensions in a Visual Studio project template, or you can package your extensions and deploy them as a Visual Studio item template. When you package your My
namespace extensions as a Visual Studio item template, you can take advantage of additional capabilities provided by Visual Basic. These capabilities enable you to include an extension when a project references a particular assembly, or enable users to explicitly add your My
namespace extension by using the My Extensions page of the Visual Basic Project Designer.
For details about how to deploy My
namespace extensions, see Packaging and Deploying Custom My Extensions.