Friday, November 30, 2012

COM is not Dead

Once in a while I get questioned why am I still using COM when there's newer technology like .NET that dominates Windows development. When I started working with DICOM the latest technology was COM and frankly speaking COM gave me harder time then DICOM back then, but after accommodating to the principals, COM had proven itself as a great way for module segregation setting clear interfaces and concrete boundaries between software components. Even now, after almost thirteen years and after countless declarations from Microsoft that COM is no longer to be supported, COM is integral part of Windows OS and actually using COM in .NET (C# or VB.NET) is much simpler then before. Even the annoyance of registering COM objects with regsvr32 no longer exists with the so simple option of side by side assemblies in .NET projects.
Eliminating regsvr32 using Side by Side assemblies Isolated flag

The reason I'm telling you all this is a little project I've been working on lately. In this project there's a department scheduler that provide the worklist through a web service but the Modalities need a DICOM Modality Worklist So I've been asked to bridge between the two. My solution was to create a plugin for the DSRSVC DICOM Server that calls the web service whenever a Modality Worklist Query is received. So the Modalities talk DICOM to the DICOM Server that translates their query to a SOAP call and then translates back the response to DICOM.
Implementing a web service client is so simple in C# and the DICOM Server plugin model already provide the Modality Worklist frameworks so all that is left to be done is to call the C# Web Service client from a DICOM Server plugin which is native C++. Ouch! How to use managed DLL from native executable? Exactly! COM! With a single check-box and couple of attributes you can turn any .NET class into a COM object and then use it in your native code.
Turning a C# Class into a COM Object
All that is left to do is to set "Register for COM interop" check-box in the .NET Class Library project properties page.
Register for COM interop flag
And now we have a .NET library ready to be called from native C++ using COM. To complete the integration we use RegAsm to add the registry entries for the COM and that's about it.

In the C++ code the TLB is imported using #import Pre-Processor directive and the method is called just like any other COM API

      _HospPatientByIDPtr api(__uuidof(HospPatientByID));
      BSTR first_name(0);
      BSTR last_name(0);
      VARIANT_BOOL res = api->GetPatientInfoByID(
             A2W(pid.c_str()), &first_name, &last_name);