The New World of .NET
Now that we have taken a look at the history of the technology, we're ready to look at the many changes that have come about with the introduction of .NET.
.NET: A Whole New Platform
I remember when I first read Mary Kirtland's articles, "Object-Oriented Software Development Made Simple with COM+ Runtime Services"1 and "The COM+ Programming Model Makes it Easy to Write Components in Any Language,"2 in Microsoft Systems Journal in 1997. In her articles, Mary discussed many of the things we know of today as .NET, but she called it COM+. At that time, it felt like a huge step and, as it turned out, it was probably too big a leap for Microsoft to take; with COM+ 1.0, they didn't leverage more than a handful of the things Mary discussed. I also remember thinking that several of the concepts were familiar to me as a COM programmer in VB, and that the C++ guys now would have some of these productivity-enhancing features too. This was also the first time I heard the expression "You can think of metadata as a type library on steroids." How many articles and books can you list that have used that expression since?
.NET Features
The following are some of the concepts that Mary discussed in her articles but that weren't fulfilled in COM+ 1.0:
A common runtime that could be used from any programming language.
Full interoperability between languages.
Attributes with a central role.
Rich metadata.
No need for manual code regarding garbage collection, class factories, and so on.
Methods used directly on classes and not only via interfaces.
Implementation inheritance.
No deterministic finalization, which means that you don't know when an object is finalized because the garbage collection may happen immediately or, most often, much later. (Yes, deterministic finalization was already mentioned at this time. I wonder why it didn't upset developers as much then.)
A strong security model for the components.
Functionality similar to SqlDataAdapter in ADO.NET. (An SqlDataAdapter can be used to register which stored procedure should be called for inserting new rows that have been added to a DataSet, for updating, and so on.)
No need for a separate interface language (such as IDL).
All languages decide on a common set of types.
Parameterized constructors and overloading.
The good news is that .NET does deliver on all of these ideas and, even years later, it's an impressive list. Although Mary's discussion was based on the idea to build the runtime and everything else on COM, .NET isn't written on COM; it's a completely new platform.
In addition, .NET also includes the following features:
Remoting (for example with SOAP)
ADO.NET
ASP.NET
Windows Forms
Web Forms
XML Web Services support
Base Class Library (BCL)
A new and a much more competent versioning schema
A new language called C#
Many changes to VB6 (or rather a rewrite) to make it Visual Basic .NET
It's important to note that even though the CLR is extremely important in .NET, it does not replace COM+. This means if your components written in managed code (that is, code managed and executed completely by the CLR) need component services, such as declarative transactions, you will still use our old friend COM+. We will discuss serviced components (components that use component services) further in a minute.
In the end, you may be asking yourself whether it is an advantage or a disadvantage to have prior experience with COM and COM+ when you enter the new world of .NET. In my opinion, it's definitely an advantage.
.NET Component Services
.NET isn't really an evolution, it's a revolution. Even so, writing serviced components (that is, using component services in .NET) is, in essence, evolutionary. If you have worked with writing components that use COM+ component services, you will be well prepared.
Listing 1.1 shows what a very simple serviced component would look like as a class in Visual Basic .NET. (For it to work, you must set a reference to System.EnterpriseServices.dll typically found in C:\WINNT\Microsoft.NET\Framework\{current version}.)
Listing 1.1 A Simple Serviced Component in Visual Basic .NET
Imports System.EnterpriseServices Public Class MyFirstSample Inherits ServicedComponent Public Function GetTime() As String Return Now.ToString End Function End Class
When this class is used for the first time, it will automatically be registered as a configured COM+ component, which comes in handy at development time. Still, at deployment time, this feature might be more of a marketing tool than something of real value, because the user running the application must have administrator privileges to have it registered. You can also use RegSvcs to manually register the component as a configured COM+ component.
COM+ object pooling will now be available to the majority of COM+ programmers, namely those who use VB6, when they shift to a .NET language, such as Visual Basic .NET or C#. An added plus is that the components you write with Visual Basic .NET and C# will not have the thread affinity problemswhich means, for example, that an object of a VB6-written class can only be used from the same thread as the one that instantiated the object because of the heavy use of Thread Local Storage (TLS) and Single Threaded Apartmentonly threading model of VB6.
A very handy feature of .NET is that the attributes can be written in code. Listing 1.2 shows an example in which a class is decorated with attributes for object pooling. Those attributes will be used as default values when the component is registered with COM+.
Listing 1.2 Attributes Decorating a Class
<ObjectPoolingAttribute(Enabled:=True, _ MinPoolSize:=2, MaxPoolSize:=3, _ CreationTimeout:=20000)> Public Class MyPooledClass
Special Considerations
You may be wondering whether the .NET programmer has to consider anything special when writing serviced components. Indeed, several things differ between writing ordinary .NET components and writing serviced ones, including the following:
You should call Dispose() when you are done with an instance of a serviced component.
You should not use nondefault constructors.
Static methods are not serviceable.
Services flow between machines, but only when DCOM is used. (That means, for example, that you must use DCOM instead of .NET Remoting if you want to use a COM+ transaction that spans two machines.)
During runtime, the user executing the COM+ application must have permission to run unmanaged code.
As usual, consumers won't have to know whether the used component is serviced or not. Of course, the consumers can be unmanaged code, such as VB6-written code. In fact, using .NET to write better COM+ components for unmanaged consumers will likely be a common scenario in the near future.