Conversion of a DicomObjects ActiveX/COM project to .NET looks initially daunting, but in fact is quite simple, and for those using any of the complicated ActionComplete/ActionUpdate mechanisms and asynchronous DicomConnection objects will find that the resulting code is lot simpler and easier to maintain after conversion. As ever, we are happy to help with any conversion issues.
The .NET version is free-threaded so all the events fire on their own threads, rather than being marshalled back onto the main thread. In general, this hugely simplifies programming, but care needs to be taken to keep objects and collections synchronised. The effects of this are different for SCUs and SCPs:
if you wish to initiate background tasks, simply use the standard .NET thread procedures to start a worker thread etc. There is no need in the .NET version to tie DicomConnection objects to DicomViewer or DicomServer objects (as there was in COM) simply to provide an attachment point for completion events
It is here that the benefit really shows - each InstanceReceived (renamed version of ImageReceived/ImageReceivedAsync) is independent of others, so you can do slow blocking operations such as writing out files, sending to a C-MOVE recipient etc. without needing to worry about tying up the main application thread.
This makes the relationship a lot clearer. DicomImage.DataSet contains all the intrinsic attributes of the DicomImage object which may be accessed via the Indexer, but contain no other information. A DicomImage on the other hand holds transient items such a zooming, flips, windowing etc.
So for instance, the same DicomImage can be present in multiple DicomImageCollection Objects, and the same is true of labels. This is a simpler model, but means that an extra parameter is now needed for many methods (e.g. label ROI functions) as the label no longer has a “hidden” owner image property.
This is in accordance with standard .NET best practice:
The DicomImages object has been renamed DicomImageCollection and DicomDataSets has been renamed DicomDataSetCollection
The same applies to collections of labels, connections etc.
The exception is the DicomAttributes collection, which has been removed altogether, as a collection of Attributes is identical in the .NET version to a DicomDataSet, so you can now use that wherever you would have used the Attributes property of a dataset (or image) in the COM version.
Also, as it only now represents a single Association at a time, the COM DicomConnection has been renamed DicomAssociation
Unlike COM version of DicomObjects, where Collections are 1 based, the new .NET version has all arrays and most of the collections 0 based.
Exceptions are where 1-based numbering is the “norm” in DICOM - i.e.:
Most of the methods that where previously available through the DicomGlobal object are still present in the DicomObjects.NET DicomGlobal object. The main difference in the .NET version is that they are all now static members, so you no longer have to create an instance of a DicomGlobal object in oder to be able to access them.
As the result of code simplification, DicomViewer object now has no networking functionalities as they should only belong to the DicomServer object.
Real registry settings are not required as all settings are kept in an internal hash table. Check Registry Values for all registry settings in DicomObjects.
DicomConnection is a confusing name when talking about networking, so we decided to give it a clearer name, DicomAssociation.
The biggest simplification has been using the native .NET matrix object to reflect any image->screen transformations. It is available in multiple overloads for screen and other purposes. The other major change is that a DicomImage no longer has a specific connection to any one DicomImageCollection and therefore it can be present in many different DicomViewers
Also, there are now several direct constructors (e.g. for reading from a file) - there is no longer a need to create a Collection merely to read a file.
Replaced Properties and Methods:
Note that the matrix object unlike the old ActualZoom accounts for non-square pixels by having different values for the X and Y scaling. In order to get a value compatible with the Zoom property, use DicomGlobal.Zoom(Matrix) to extract the minimum scaling value.
The number of properties has been reduced markedly, mainly by using native .NET objects, so here are a few conversion pointers for specific COM properties: