Browse DevX
Sign up for e-mail newsletters from DevX


Moving DNA applications from COM+ to .NET: Drill down to Serviced Components

The question "Is COM dead?" has been hanging around since the release of the .NET PDC Technology preview. Having played with two beta versions of the .NET framework, most of us agree that COM is actually dead as a binary standard. The interface based programming model is still alive though.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

he whole set of COM+ services are made available in .NET via a set of classes gathered into the System.EnterpriceServices namespace. Such classes are implemented in the shared assembly named System.EnterpriseServices.dll.

Almost all COM+ settings have their .NET attribute counterpart. Using .NET attributes at the proper level (method, interface, class, assembly) it’s possible to control any aspect of the exporting process of a .NET assembly to a COM+ application (read the regdb). There are just a few settings, like the process identity (the user/password pair) of a server COM+ application that can’t be, reasonably, set in the .NET assembly code.

Note that, in some cases, the .NET runtime reads the assembly metadata and not the COM+ catalog to apply COM+ related settings. It’s not quite clear if this is a beta bug or a desired behavior (maybe for performance reasons). In any case, it’s better to check that altering manually COM+ settings on a .NET derived COM+ application using the Component services snap-in has the expected results.

COM and COM+ Attributes
You typically deploy a class that wants to take advantage of COM+ services (known as Enterprise Services in the .NET world) into a Class library assembly. The basic requirement is to derive the class from the ServicedComponent class (note that such class derives from MarshalbyRefObject); of course, you do that after you’ve added a reference to System.EnterpriseServices.dll in to the project, as shown below.

In the next step you can go directly to define and implement the methods your class exposes or (better) define an interface first and then have the class implement it. In both cases .NET requires you to specify how the class public methods or the interface should be exposed to the COM+ world. This means that you have to specify if the interface and/or the public class methods must be exposed as pure IUnknown, Dual or pure IDispatch interfaces. This can be done specifying, respectively, the InterfaceTypeAttribute and ClassInterface at the proper level as shown in code snipped below

<InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface Imyinterface
    Function mymethod(ByVal a As Long, ByRef x As String) As Long
End Interface
<ClassInterface(ClassInterfaceType.AutoDispatch)> _
Public Class class1
    Inherits ServicedComponent
End Class

The ComInterfaceType enum exposes the following entries


While the ClassInterfaceType exposes


Note that None is the default in beta2, hence you’ll have to specify a ClassInterface attribute to make the class methods available to COM. There is one, most time, undesired side-effect in publishing class public methods directly: public methods of classes your class derives from are exposed as well; as a consequence, you’ll get, at least, the public methods of System.Object exposed by your class "for free".

Defining explicitly the interface, and then having the class implementing it, is the recommend solution; if you do so, you can omit the ClassInterfaceType on the class.

There are other COM related settings you can declare explicitly like the interface and class UUID and the class progid; again these settings are applied via attributes

<GuidAttribute("990829A9-AE62-431c-A940-3714047BDC0E"), _
ProgIdAttribute("class1"), _
ClassInterface(ClassInterfaceType.AutoDispatch)> _
Public Class class1
  Inherits ServicedComponent
End Class

COM+ related attributes are declared in a similar way. If you omit an attribute the .NET framework make a default choice (as the COM+ runtime does when importing a class into the COM+ catalog); The .NET framework is clever enough in this situation to adapt its default choice not to be inconsistent with explicitly declared attribute, e.g., when a class declares to require transaction, its synchronization attribute is set to required.

<GuidAttribute("990829A9-AE62-431c-A940-3714047BDC0E"), _
ProgIdAttribute("myclass1"), _
JustInTimeActivation, _
ObjectPooling(MinPoolSize=5, MaxPoolSize=5, Enabled=true), _
//implicit by JITA Synchronization(SynchronizationOption.Required), _
COM+ Application Attributes
COM+ application level settings are set via attributes declared at the assembly level, that is in the Assemblyinfo.vb file. In this sample the assembly will be deployed into a library COM+ application whose name is NetComponent

<Assembly: ApplicationActivation(ActivationOption.Library)>
<Assembly: ApplicationName("NetComponent")>
<Assembly: ApplicationIDAttribute

Any Serviced component must be hosted into a strongly signed assembly; to do this you must first run the sn.exe utility with the -k switch to generate a file containing the public/private key pair. You then sign the assembly with the key pair adding the following line in the assemblyinfo.vb file

<assembly: AssemblyKeyFile("mykey.snk")>

It’s highly recommended that you deploy the assembly into the GAC, if you fail to do so, just remember that the .NET runtime binding policy applies to such assembly as well: having the assembly registered in a COM+ application is not what a com developer tends to think. From a COM+ perspective all registered serviced components are implemented in mscoree.dll (more on it later).

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date