|
Introduction
.NET is Microsoft's next-generation component technology. It is
designed from the ground up to simplify component development
and deployment, as well as to support interoperability between
programming languages. Despite its innovations and modern design,
.NET is essentially a component technology. Like COM, .NET provides
you with the means to rapidly build binary components, and Microsoft
intends for .NET to eventually succeed COM. Like COM, .NET does
not provide its own component services. Instead, .NET relies on
COM+ to provide it with instance management, transactions, activity-based
synchronization, granular role-based security, disconnected asynchronous
queued components, and loosely coupled events. The .NET namespace
that contains the types necessary to use COM+ services was named
System.EnterpriseServices to reflect the pivotal role it plays
in building .NET enterprise applications. A .NET component that
uses COM+ services is called a serviced component
to distinguish it from the standard managed components in .NET.
Developing Serviced Components
A .NET component that takes advantage of COM+ services needs
to derive from the .NET base class ServicedComponent. ServicedComponent
is defined in the System.EnterpriseServices namespace. To develop
a simple Serviced components following steps has to be followed:
| » |
Define a class that derives directly or indirectly from
the ServicedComponent class. For example, the following code
ensures that the CMN_Terms class is hosted by a COM+ application: |
| |
Imports
System.EnterpriseServices
Public Class CMN_Terms
Inherits ServicedComponent |
| » |
Apply service attributes to the assembly, class, or method. |
| |
Imports
System.EnterpriseServices
<Transaction(TransactionOption.Required)>
_
Public Class CMN_Terms
Inherits ServicedComponent
<AutoComplete()>
Public Sub DoSomething()
End Sub
End Class |
| » |
Deploy the serviced component application by registering
its assemblies dynamically or manually. |
After a serviced component is registered, clients can create
instances of the component the way they create instances of any
other component.
There are two ways to configure a serviced component to use COM+
services. The first is COM-like: you derive from ServicedComponent,
add the component to a COM+ application, and configure it there.
The second way is to apply special attributes to the component,
configuring it at the source-code level. When the component is
added to a COM+ application, it is configured according to the
values of those attributes. Attributes are discussed in greater
detail below under custom attributes chapter.
.NET allows you to apply attributes to your serviced components
with great flexibility. If you do not apply your own attributes,
a serviced component is configured using default COM+ settings
when it is added to a COM+ application. You can apply as many
attributes as you like. A few COM+ services can only be configured
via the Component Services Explorer. These services are mostly
deployment-specific configurations, such as persistent subscriptions
to COM+ Events and allocation of users to roles. In general, almost
everything you can do with the Component Services Explorer can
be done with attributes. It is recommended that you put as many
design-level attributes as possible (such as transaction support
or synchronization) in the code and use the Component Services
Explorer to configure deployment-specific details.
Registering Serviced Components
A Serviced Component is hosted by a COM+ application and
must be accessible to that application. For accessibility, serviced
components have the following registration and configuration requirements:
| » |
Assembly must be strong-named |
| » |
Assembly must be registered in the Windows registry. |
| » |
Type library definitions must be registered and installed
into a specific COM+ application. |
| » |
Services added programmatically must be configured in the
COM+ catalog. |
You can perform that registration in three ways:
| » |
Manually, using a command line utility called RegSvcs.exe. |
| » |
Dynamically, by having the client program register your
assembly automatically. |
| » |
Programmatically, by writing code that does the registration
for you using a utility class provided by .NET. |
Regardless of the technique you use, the registration process
adds your serviced components to a COM+ application and configures
them according to the default COM+ settings or according to their
attributes (if present in the code). If the assembly contains
incompatible attributes, the incompatibility is detected during
registration and the registration is aborted. Future versions
of the .NET compilers may detect incompatibilities during compilation
time.
Manual Registration
To register your component manually, use the RegSvcs.exe
command-line utility. RegSvcs accepts as a parameter the name
of the file containing your assembly's metadata. In a single DLL
assembly, that file is simply the assembly file. If you do not
specify as an assembly attribute the name of the COM+ application
that should host your components, RegSvcs must be told that name
explicitly as a command-line parameter, using the /appname: switch.
For example, if your single DLL assembly resides in MyAssembly.dll
and you wish to add the serviced components in that assembly to
the MyApp COM+ application, you would use RegSvcs in this manner:
RegSvcs.exe /appname: MyApp MyAssembly.dll |
The command-line application name is ignored if the assembly
contains an application name.
If you don't specify a COM+ application name, either in the assembly
or as a command-line parameter, RegSvcs uses the assembly name
for the application name. If your assembly is called MyAssembly,
RegSvcs adds the components to the MyAssembly COM+ application.
This behavior is the same for all the command-line switches.
When RegSvcs adds a serviced component to the COM+ Catalog, it
must give it a class-ID (CLSID) and a prog-ID. RegSvcs creates
a GUID for every component (based on the assembly's version and
the class definition) and names it < Namespace>.<Component
name>. You can also specify the CLSID and the prog-ID of your
serviced components using attributes.
In addition to adding the serviced components in the assembly
to a COM+ application, RegSvcs creates a type library. This library
contains interface and CoClass definitions to be used by nonmanaged
clients (COM clients). The default type library filename is <Assembly
name>.tlb--the name of the assembly with a .tlb extension.
Dynamic Registration
When a managed client creates a serviced component, the .NET
runtime resolves which assembly version to use for that client.
Next, the runtime verifies that the required version is registered
with COM+. If it is not registered, the runtime installs it automatically.
This process is called dynamic registration. As with RegSvcs,
if the assembly contains an application name, then that name is
used; if it does not, then the assembly's name is used for the
COM+ application's name.
Note that only .NET clients can rely on having dynamic registration
done when they instantiate a .NET serviced component. For COM
clients, you must use the RegSvcs utility. Another limitation
of dynamic registration is that serviced components in the assembly
are configured according to the attributes in the assembly and
the COM+ defaults. If you require configuring some services (such
as events subscriptions) using the Component Services Explorer
for your application to function properly, you must use RegSvcs
to register your components and provide the additional configuration
using the Component Services Explorer. Only then can clients use
your serviced components. As a result, dynamic registration is
only useful for serviced components that contain all the service
configurations they need in their code through the use of attributes.
Finally, dynamic registration requires that the user invoking
the call that triggers dynamic registration be a member of the
Windows 2000 Administrator group. It has this requirement because
dynamic registration makes changes to the COM+ Catalog; if the
user invoking it is not a member of the Windows 2000 Administrator
group, dynamic registration will fail.
In general, you should use RegSvcs and the Component Services
Explorer rather than relying on dynamic registration. If you want
to rely on dynamic registration of your serviced components, you
should increment the version number of your assembly every time
you make a change to one of the components' attributes, to ensure
that you trigger dynamic registration.
Programmatic Registration
Both RegSvcs and dynamic registration use a .NET class called
RegistrationHelper to perform the registration. RegistrationHelper
implements the IRegistrationHelper interface, whose methods are
used to register and unregister assemblies. For example, the InstallAssembly(
) method registers the specified assembly in the specified COM+
application (or the application specified in the assembly). This
method is defined as:
Public
Sub InstallAssembly( _
ByVal
assembly As String, _
ByRef
application As String, _
ByRef
tlb As String, _
ByVal
installFlags As InstallationFlags _
) |
The installation flags correspond to the various RegSvcs switches.
See the MSDN Library for additional information on RegistrationHelper.
CONFIGURING SERVICED COMPONENTS
Specifying Application Name
You can provide .NET with an assembly attribute, specifying the
name of the COM+ application you would like your components to
be part of, by using the ApplicationName assembly attribute:
<Assembly: ApplicationName("ESS_CMN")> |
If you do not provide an application name, .NET uses the assembly
name. The ApplicationName attribute (and the rest of the serviced
components attributes) is defined in the System.EnterpriseServices
namespace. You must add this namespace to your project references
and reference that namespace in your assembly information file:
imports System.EnterpriseServices; |
The ApplicationID Attribute
Every COM+ application has a GUID identifying it called the application
ID. You can provide an assembly attribute specifying the application
ID in addition to the application name:
<Assembly: ApplicationID("8BE192FA-57D0-49a0-8608-6829A314EEBE")> |
Unlike the application name, the application ID is guaranteed
to be unique, and you can use it alongside the application name.
Once an application ID is specified, all searches for the application
during registration are done using the application ID only, and
the application name is only useful as a human-readable form of
the application identity.
The Guid Attribute
Instead of having the registration process generate a CLSID for
your serviced component, you can specify one for it using the
Guid attribute:
imports
System.Runtime.InteropServices;
<Guid ("260C9CC7-3B15-4155-BF9A-12CB4174A36E")>
Public Class WebNS
Inherits ServicedComponent
'Code Here
End Class |
The Guid attribute is defined in the System.Runtime.InteropServices
namespace.
When you specify a class ID, subsequent registrations of the assembly
don't generate a new CLSID for the component, regardless of the
version of the assembly being registered. Registrations always
reconfigure the same component in the COM+ Catalog. Specifying
a class ID is useful during development, when you have multiple
cycles of code-test-fix. Without it, every invocation by the test
client triggers a dynamic registration--you very quickly clutter
the COM+ application with dozens of components, when you actually
only use the latest one.
The ProgId Attribute
Instead of having the registration process generate a name for
your serviced component (namespace plus component name), you can
specify one for it using the ProgID attribute:
Imports
System.Runtime.InteropServices
<ProgId("CMN_Terms.WebNS")>
Public Class
WebNS
Inherits ServicedComponent
'Code Here
End Class |
The ProgId attribute is defined in the System.Runtime.InteropServices
namespace.
Application Activation Type
To specify the COM+ application's activation type, you can use
the ApplicationActivation assembly attributes. You can request
that the application be a library or a server application:
<assembly:
ApplicationActivation(ActivationOption.Server)>
or:
<assembly:
ApplicationActivation(ActivationOption.Library)> |
If you do not provide the ApplicationActivation attribute, then
.NET uses a library activation type by default. Note that this
use differs from the COM+ default of creating a new application
as a server application.
The Description Attribute
The Description attribute allows you to add text to the description
field on the General Properties tab of an application, component,
interface, or method. After registration, the assembly-level description
string becomes the content of the hosting COM+ application's description
field; the class description string becomes the content of the
COM+ component description field. The interface and method descriptions
are mapped to the corresponding interface and method in the Component
Services Explorer
COM+ Object Pooling
The ObjectPooling attribute is used to configure every aspect
of your component's object pooling. The ObjectPooling attribute
enables or disables object pooling and sets the minimum or maximum
pool size and object creation timeout. For example, to enable
object pooling of your component's objects with a minimum pool
size of 3, a maximum pool size of 10, and a creation timeout of
20 milliseconds, you would write:
<ObjectPooling(MinPoolSize=3,MaxPoolSize=10,CreationTimeout=20)>
Public Class
WebNS
Inherits ServicedComponent
'Code Here
End Class |
The MinPoolSize, MaxPoolSize, and CreationTimeout properties
are public properties of the ObjectPooling attribute class. If
you do not specify values for these properties (all or just a
subset) when your component is registered, the default COM+ values
are used for these properties (a minimum pool size of 0, a maximum
pool size of 1,048,576, and a creation timeout of 60 seconds).
COM+ Constructor String
Any COM+ configured component that implements the IObjectConstruct
interface has access during construction to a construction string,
configured in the Component Services Explorer. Serviced components
are no different. The base class, ServicedComponent, already implements
the IObjectConstruct interface as a virtual method (it has only
one method). Your derived serviced component can override the
Construct( ) method, as shown in this code sample:
Public
Class WebNS
Inherits ServicedComponent
Protected
Overrides Sub Construct( _
ByVal constructString
As String)
If Not constructString
Is Nothing Then
mstrConstructionString
= constructString
End If
End Class
|
If the checkbox "Enable object construction" on the
component Activation tab is selected, then the Construct( ) method
is called after the component's constructor, providing it with
the configured construction string.
You can also enable construction string support and provide a
default construction string using the ConstructionEnabled attribute:
<ConstructionEnabled(Enabled=true,
Default = "My String")>
Public Class
WebNS
Inherits ServicedComponent
End Class |
The ConstructionEnabled attribute has two public properties.
Enabled enables construction string support for your serviced
component in the Component Services Explorer (once the component
is registered) and Default provides an initial string value. When
your component is registered with COM+, the registration process
assigns the default string to the constructor string field on
the component Activation tab. The default string has no further
use after registration. New instances of your component receive
as a constructor string the current value of the constructor string
field. For example, if the default string is String A, when the
serviced component is registered, the value of the constructor
string field is set to String A. If you set it to a different
value, such as String B, new instances of the component get String
B as their construction string. They receive the current value,
not the default value.
COM+ Transactions
You can configure your serviced component to use the five available
COM+ transaction support options by using the Transaction attribute.
The Transaction attribute's constructor accepts an enum parameter
of type TransactionOption, which has following five values:
| » |
Disabled, |
| » |
NotSupported, |
| » |
Supported, |
| » |
Required, |
| » |
RequiresNew. |
For example, to configure your serviced component to require
a transaction, use the TransactionOption.Required value:
<Transaction(TransactionOption.Required)>
Public Class
WebNS
Inherits ServicedComponent
End Class |
STRONG NAMED ASSEMBLIES
A strong name consists of the assembly's identity---it's simple
text name, version number, and culture information (if provided)---plus
a public key and a digital signature. It is generated from an
assembly file (the file that contains the assembly manifest, which
in turn contains the names and hashes of all of the files that
make up the assembly), using the corresponding private key. Once
an assembly is created, you can not sign it with a strong name.
To create a strong-named assembly, you must sign it with a strong
name when you create it.
For creating a strong named assembly ,You need to Create a cryptographic
key pair using the Strong Name tool (Sn.exe) and assign that key
pair to the assembly using either a command-line compiler or the
Assembly Generation tool (Al.exe)). The .NET Framework SDK provides
both Sn.exe and Al.exe.
To create a key pair
At the command prompt, type the following command:
In this command, file name is the name of the output file containing
the key pair. The following example creates a key pair called
sgKey.snk.
Signing an Assembly with a Strong Name
There are two ways to sign an assembly with a strong name:
| » |
Use the Assembly Generation tool (Al.exe) provided by the
.NET Framework SDK. |
| » |
Use assembly attributes to insert the strong name information
in your code. You can use either the AssemblyKeyFileAttribute
or the AssemblyKeyNameAttribute, depending on where the key
file to be used is located. |
To create and sign an assembly with a strong name using
the Assembly Generation tool
At the command prompt, type the following command:
al /out:<assembly name> <module name> /keyfile:<file
name> |
In this command, assembly name is the name of the assembly to
sign with a strong name, module name is the name of the code module
used to create the assembly, and file name is the name of the
container or file that contains the key pair.
The following example signs the assembly MyAssembly.dll with a
strong name using the key file sgKey.snk
al /out:MyAssembly.dll MyModule.netmodule /keyfile:sgKey.snk
|
To sign an assembly with a strong name using attributes
In a code module, add the AssemblyKeyFileAttribute or AssemblyKeyNameAttribute
assembly attribute specifying the name of the file or container
that contains the key pair to use to sign the assembly with a
strong name. The following code example uses the AssemblyKeyFileAttribute
with a key file called sgKey.snk.
<Assembly:AssemblyKeyFileAttribute("sgKey.snk")> |
Installing an Assembly into the Global Assembly Cache
When an assembly that uses ApplicationActivationOption is set
to server, the assembly is loaded by dllhost.exe, which most likely
is not in the same directory as the client. Assemblies that use
serviced components in COM+ server apps should be placed in the
GAC. Assemblies that use serviced components in COM+ libraries
apps may not need to be placed in the GAC (unless they are located
in different directories). The only exception is when hosting
with ASP.NET—assemblies should not be placed in the GAC to enable
shadow copy to operate correctly. So it is better to place all
serviced components inside the GAC.
There are two ways to install an assembly into the global assembly
cache:
| » |
Using the Windows Installer 2.0.
This is the recommended and most common way to add assemblies
to the global assembly cache. The installer provides reference
counting of assemblies in the global assembly cache and other
benefits. |
| » |
Using the Global Assembly Cache tool (Gacutil.exe).
You can use Gacutil.exe to add strong-named assemblies to
the global assembly cache. This tool can also be used to view
the contents of the global assembly cache. |
To install a strong-named assembly into the global assembly
cache
At the command prompt, type the following command:
gacutil –i <assembly name> |
In this command, assembly name is the name of the assembly to install
in the global assembly cache. The following example installs an
assembly with the file name hello.dll into the global assembly cache.
CONCLUSION
This article explains how to develop and deploy serviced components
in Visual Basic .Net. It also explains about custom attributes
which is used in COM+ services.
For comments and feedback, mail me at saravana@yahoo.com
|