Summary: Overview of how the My function exposes .NET Framework functionality, including available classes, dynamically generated classes, and threading.
Note: This article and sample code are based on the pre-release version of Microsoft Visual Studio 2005 (previously codenamed "Whidbey"). All information contained herein is subject to change. The sample project requires Visual Studio2005Beta1 or higher.
Introduction
My is a new feature in Visual Basic 2005 that puts frequently used functionality at your fingertips and reduces the number of lines of code you have to write. It does this in an efficient, reliable and thread-safe way. In an environment where programmer productivity is particularly important, My can help you complete your work faster. This is the essence of Visual Basic.
The purpose of this article is to explore how to use My to access .NET Framework functionality and items in your project.
.NETFramework classes available from My
Because there is so much involved in .NET Framework, it can be difficult to find the functionality you need. To solve this problem, My provides entry points to commonly used .NET Framework classes and functions. My also exposes new high-level .NET Framework classes that aggregate related functionality into task-based APIs.
My exposes functionality by returning a .NETFramework class that is instantiated and ready for use, deferring calls to .NETFramework methods, and returning dynamically generated classes that can be used to access items in your project.
Directly public
Whenever possible, My serves as a discovery mechanism for existing classes in the .NET Framework and exposes these types directly. See the following My.application.Deployment example:
PublicReadOnlyPRpertyDeployment()As_
System.Deployment.ApplicationDeployment
Get
Return_
System.Deployment.ApplicationDeployment.CurrentDeployment
EndGet
EndProperty
Other examples of direct exposure include My.Computer.FileSystem.OpenTextFileReader() (which returns System.IO.StreamReader), My.Application.OpenForms() (which returns System.Windows.Forms.FormsCollection), My.User (which returns System.Security.Principal.IPrincipal), etc.
Appearance
My can also return new classes that provide a task-based API for performing operations that were previously difficult to perform because finding functionality was difficult and/or required multiple objects to work together.
Common tasks that require using the low-level .NET Framework API or require multiple lines of code are greatly simplified. See the following task example to determine whether a network connection is available:
ImportsSystem.Net.NetworkInformation
PublicReadOnlyPropertyIsAvailable()AsBoolean
Get
ForEachNetInterfaceAsNetworkInterfaceIn_
NetworkInterface.GetAllNetworkInterfaces()
IfNetInterface.Type<>InterfaceType.Loopback_
AndAlsoNetInterface.Type<>InterfaceType.Tunnel_
AndAlsoNetInterface.OperationalStatus=_
OperationalStatus.UpThen
ReturnTrue
EndIf
Next
ReturnFalse
EndGet
EndProperty
The above code requires detailed knowledge of several types in the System.Net.NetworkInformation namespace. Using the appearance pattern, My.Computer.Network reduces these types and their relationships to a single line of code: My.Computer.Network.IsAvailable().
Appearances can also simply bring together related functionality that would otherwise be hard to find. For example, My.Computer brings together properties from different classes to provide the computer name and access to the screen:
PublicReadOnlyPropertyName()AsString
Get
ReturnSystem.Environment.MachineName
EndGet
EndProperty
PublicReadOnlyPropertyScreen()AsSystem.Windows.Forms.Screen
Get
ReturnSystem.Windows.Forms.Screen.PrimaryScreen
EndGet
EndProperty
Other examples of classes in My that bring together related functionality from multiple .NET Framework types include My.Application, My.Computer, My.Computer.FileSystem, My.Computer.Info, and My.Application.Info.
Proxy class
The proxy class is a very "thin" class that forwards all calls to it to the base object. For example, if you call My.Computer.Clipboard.GetText(), you are actually calling the proxy class method ClipboardProxy.GetText(), defined as follows:
PublicFunctionGetText()AsString
ReturnClipboard.GetText()
EndFunction
By convention, proxy classes always have the suffix Proxy. My uses proxies when accessing the clipboard, file system, and registry because the base classes exposed by proxies are composed of shared methods that are not visible in IntelliSense. The Proxy class cannot be instantiated by the user. Performance testing has shown that forwarding calls through a proxy makes no sense.
Dynamically generated classes
In line with the purpose of "putting functionality at your fingertips," My provides access to the forms, Web services, resources, and settings defined in your project. For example, if your project contains a reference to the web service MapDirections, you can use the web service immediately without having to know how to start an instance of the web service proxy. You just type the following: My.WebServices.MapDirections.GetDirections(...)
How does this work? Factory classes are generated by a compiler that returns lazily created instances on demand for the forms, web services, settings, and resources in your project. The factory class is adapted to return instances in a manner suitable for the type of project (exe/dll/web) in which your code is running. See the "Threading" section for more details.
My.Forms
As an example of a dynamically generated class, consider My.Forms. This class is provided to you and defines factory methods for each form in your project. When you access the Form through My.Forms.Form1, the factory method checks to see if an instance of Form1 is already open. If an instance is already open, that instance is returned. Otherwise, an instance of Form1 is created and returned. The generated code for the project containing Form1 looks like this:
ClassMyForms
'Codeinboldisgeneratedbythecompiler
Publicm_Form1AsForm1
PublicPropertyForm1()AsForm1
Get
m_Form1=Create__Instance__(OfForm1)(m_Form1)
Returnm_Form1
EndGet
Set(ByValValueAsForm1)
IfValueIsm_Form1
Return
EndIf
IfNotValueIsNothingThen
ThrowNewArgumentException(_
PropertycanonlybesettoNothing.)
EndIf
Dispose__Instance__(OfForm1)(m_Form1)
EndSet
EndProperty
EndClass
The Create__Instance__() function is responsible for creating instances of the form on demand. It checks whether the form (stored in m_Form1) has been instantiated. If the form has already been instantiated, the form is returned. Otherwise, an instance is created and returned. Create__Instance__() also captures recursive form creation attempts. Dispose__Instance__() is responsible for closing the form.
My.Forms also provides a method for reintroducing a default instance of a form, which you may be familiar with from earlier versions of Visual Basic. Default instances make it possible to reference an instance of a form without first explicitly creating an instance of the form.
For example, in Visual Basic 6.0, you might have written Form1.Show() instead:
DimForm1InstanceasForm1
Form1Instance=newForm1
Form1Instance.Show()
Because the compiler in Visual Basic 2005 uses My.Forms to create default instances, you can just write Form1.Show().
My.WebServices
One of the difficulties people encounter when coding web services is determining which class to code against. My.WebServices eliminates this determination process and provides instances of Web service proxies on demand.
My.WebServices is best suited for synchronous calls to Web services. The code pattern generated to provide an instance of the Web service proxy is the same as the code pattern shown to return an instance of the form.
My.Settings
New in Visual Basic 2005 is the Settings Designer, which lets you specify application settings on an application or user basis. The designer creates a class that you can use to access your settings in a strongly typed way. You can see an example of the MySettings class by showing All Files in Solution Explorer and looking for the MySettings.vb file under the MySettings.Settings node.
The following is an example of a property generated to manage an application setting named SampleUserSetting:
PartialNotInheritableClassMySettings
InheritsSystem.Configuration.ApplicationSettingsBase
<System.Diagnostics.DebuggerNonUserCode(),_
System.Configuration.UserScopedSettingAttribute(),_
System.Configuration.DefaultSettingValueAttribute(TryMe)>_
PublicPropertySampleUserSetting()AsString
Get
ReturnCType(Me(SampleUserSetting),String)
EndGet
Set
Me(SampleUserSetting)=value
EndSet
EndProperty
EndClass
The generated classes do all the heavy lifting for you. To access this setting, just type:
My.Settings.SampleUserSetting
My.Resources
Another new feature in Visual Basic 2005 is the Resource Designer, which enables you to add resources to your application. The Resource Designer also creates a module that you can use to access resources in your application in a strongly-typed way. For example, if you add a bitmap named Smiley to your project, you can access the bitmap using My.Resources.Smiley. You can see an example of the generated resource module by displaying All Files in the sample project's Solution Explorer and looking for the MyResources.vb file under the MyResources.resx node.
The following is an example of a sample project generated to return a factory property for a Smiley resource:
PublicReadOnlyPropertySmiley()AsSystem.Drawing.Bitmap
Get
ReturnCType(ResourceManager.GetObject(Smiley,_resCulture),_
System.Drawing.Bitmap)
EndGet
EndProperty
The generated strongly typed resource module handles case-sensitive resource IDs, uses the System.Resources.ResourceManager class to retrieve your resources, and manages the details related to getting the ResourceManager correctly created for your application.
To access the same Smiley bitmap in VisualBasic2002 or VisualBasic2003, you first have to put the bitmap into a .resx file, which is difficult. Another way is to put it into the project as an embedded resource and you have to remember to change the build action in the properties grid of the resource that is going to be the embedded resource. In this way, the code you write should look like this:
DimCurrentAssemblyAsReflection.Assembly=_
Reflection.Assembly.GetExecutingAssembly
DimBitMapStreamAsIO.Stream=_
CurrentAssembly.GetManifestResourceStream(_
WindowsApplication2.Smiley.bmp)
DimSmileyBitmapasDrawing.Bitmap=NewBitmap(BitMapStream)
There are some important details in this code that you need to know. You have to know to get the currently executing assembly and call GetManifestResourceStream() on it. You must remember to qualify resource names with the root namespace name. You must get case permission because the name passed to GetManifestResourceStream() is case-sensitive. You must know where to define the stream class so that you can capture the return value of GetManifestResource in the stream object. You must know how to create a bitmap from a stream. You may encounter frustration when trying to determine why a BitMapStream always returns Nothing due to one of the above issues.
Visual Basic 2005 solves the first problem by providing ResourceEditor, which makes it easy to place new or existing resources into .resx files. These resources can then be easily accessed using My. All you need to do is write the following:
DimSmileyBitmapasDrawing.Bitmap=My.Resources.Smiley
Threading
The class instances available in My are exposed in a way that alleviates threading issues, because instances of My objects are provided on a per-thread basis. That is, the instance of My.Computer returned on thread 1 is different from the instance of My.Computer returned on thread 2. This means you don't have to write synchronization code when using the My object.
In a web application, the instance returned from My is stored on request.
summary
We've looked at how My exposes .NET Framework classes and how dynamically generated classes can be generated to complement My.
Finally, My reduces the number of lines of code you have to write and provides access to commonly used functionality. It does this in an efficient, reliable and thread-safe way. In an environment where programmer work efficiency is particularly important, My can help you complete your work more quickly and effectively.
->