现在的位置: 首页 > 综合 > 正文

Migrating Delphi Applications to .NET

2012年06月23日 ⁄ 综合 ⁄ 共 7196字 ⁄ 字号 评论关闭
文章目录

I just came by a fairly new set of Delphi tools by CodeGear and RemObjecs, and being an ex Delphi programmer, my mind was flooded with intriguing ideas. How easy would it be to port old Delphi applications into this century, i.e. the .NET world, without the need of a complete rewrite? This would not be the first time it is attempted, but would it be easier now with these brand new tools?

If you have read so far, you probably already know what Delphi is. What you might not know is that CodeGear (now owned by Embarcadero Technologies) released a new .NET version of Delphi just a few months ago. Called Delphi Prism (just Prism here from now on), this MS Visual Studio plug-in is based on Oxygene CLR compiler licensed from RemObjects and fully compliant with the .NET Framework. Both Delphi and Prism compile their own dialect of the Pascal language, of course.

The first attempt towards .NET by Borland/CodeGear was Delphi.NET that first appeared as Delphi 8 in 2003. At first it aroused some enthusiasm, but after all it was no success and was never updated to .NET Framework 2.0. Oxygene/Prism, on the other hand, is not based on Delphi.NET and supports the whole .NET Framework up to version 3.5 and probably beyond.

Porting Delphi Code to .NET

Now, thanks to Prism, you might think that in order to get a .NET application all you would have to do is compile the Pascal sources with Prism, with minor syntax adjustments, perhaps. Well, for your disappointment I have to tell you that there is much more to it than just recompiling the source code. Let’s take a look at a minimal Windows application written in Delphi and Prism!

All this application does is stuff the current date and time into a label that was placed on the main form of the application. The Delphi version looks like this:

Delphi sample

And here’s the Prism version:

Prism sample

Because it’s also written in Pascal, this code bears some structural resemblance to Delphi, but the single line of functional code in our application looks quite different in these two cases: label1.Caption := FormatDateTime(‘c’, Now) vs. label1.Text := DateTime.Now.ToString().

For comparison, let’s have a look at the same application in C#:

C# code sample

The key thing here is the library, namely VCL in Delphi vs. .NET Framework in Prism (or C#). Yes, there is a Label control in both environments, but the most important property bearing the text content is named differently. And to get the current date and time, you would access the Now static property of the DateTime .NET class in Prism whereas in Delphi you would call the Now function that is not part of any class – to say nothing of the formatting of this DateTime value into a string. And this is just the beginning!

Delphi.NET tried to cloak the .NET Framework with VCL.NET, a VCL look-alike that acted as a wrapper around the .NET Framework and implemented the essentials of VCL as calls to .NET. It must have been quite a job to create VCL.NET, and porting it to .NET Framework 2.0 seems to have been even a harder one because it was never really attempted. Moreover, VCL.NET was a dead end because it did not provide a migration path to pure .NET Framework – if you started using VCL.NET, you would be stuck with the VCL object model for the rest of your career!

A more recent undertaking to create a VCL-topping on .NET Framework is ShineOn, an Open Source project initiated by CodeGear. The current version, sorry to say, is just a skeleton that has barely anything implemented. Knowing what happened to VCL.NET, one cannot expect very much from this project. It would be a daunting task to develop a comprehensive VCL replacement that perfectly maps VCL to .NET and does it with no performance penalty.

If these problems with libraries are not enough, look at the Delphi and Prism code samples above! Starting with the word Namespace, there are differences in structure and syntax that originate from the fact that Prism is a .NET language. To alleviate this problem, RemObjecs is developing a tool named Oxidizer that promises to “take care of a lot of the grunt work” that is needed when porting code with manual tools such as search and replace. When it works, Oxidizer can be a great help, but in the end reviewing and finishing the Prism code is something you will always have to do manually in the code editor.

Converting Visual Layouts

You may have noticed that the code samples above were not complete Windows programs – the visual form layouts were missing. We know that VCL forms store they layouts in .dfm files whereas the .NET form designer writes normal program code (Windows Forms) or XAML (WPF). Translating text-based .dfm code to C#, Pascal or XAML is basically something a translator program could do provided it knows the mapping between the UI controls and their properties in VCL and Windows Forms or WPF. Such a tool does not exist yet, but building one is the least of our problems. Even if the tool cannot find a 100 % mapping between the libraries, the amount of manual work is essentially smaller than porting general-purpose program code.

Best of Both Worlds: Running Side by Side

Another option to migrate to .NET would be keep your old native Delphi code as it is and link it with new managed code written in Prism. Calling unmanaged code from Prism or C# is no big deal, but the opposite is also possible. Although linking managed assemblies to Delphi is not as straightforward as linking native Delphi units, it can be done using one of a few routine methods that developers use every day when they move from C, C++ or Visual Basic 6 to C#.

The most common method is to use COM. Assemblies written with Prism or C# can be registered as COM objects that Delphi is able to call, and vice versa. The downside of COM is those woes that made .NET so welcome: the necessity to register all COM objects and the notorious DLL Hell. Were your application anything but trivial, very soon you would have to register and maintain several COM interfaces between Delphi and .NET.

Another method is to use mixed-mode DLL’s that have interfaces to both .NET and native WIN32 code. Unfortunately, they must be written in C++ so you would have to add a third programming language in the mixture.

But luckily there’s still another method, from RemObjects, again! They are selling a tool named Hydra that is based on the concept of plugins. Both plugins and plugin hosts can be written using Delphi or a .NET language (Prism, C# etc.), and thus Delphi applications can host .NET plugins, and .NET applications can host Delphi plugins. Plugins can be visual (kind of user controls) and non-visual (e.g. business components).

Hydra provides a set of wizards and helper components that open windows to the other world through interfaces. Calling the other side through an interface requires some typecasting or late binding, but it seems to work. The best thing is that Hydra does not use COM.

Which Way to Go?

As we have seen, porting Delphi code through Prism to the .NET world is not as easy as it would seem at first glance. If your code interacts with the user interface or relies heavily on VCL components such as datasets, there will be lots of manual work ahead. Only if your code mainly deals with your own classes and barely touches the run-time library, the porting solution would be feasible, but because we are porting a RAD solution, such a situation should not be very frequent. After all, the idea behind RAD has been to rely on smart components and controls, not to write everything from scratch.

What I would recommend is to start in a step-by-step fashion and implement new features and modules as .NET plugins. Depending on the structure of your application, a whole application layer, say the data access layer, could also be implemented as a .NET plugin. A VCL ClientDataSet fed by an ADO.NET plugin sounds quite realistic.

Over time, more and more modules would be migrated, and one day you could translate your form layouts from DFM to XAML, run a raw code translation to Prism with Oxidizer and hand-tune the rest. Personally, I would translate the code all the way to C#, but it’s your choice which .NET language you like to use.

If you are planning to stick with Delphi and completely ignore the evolving .NET world around you, don’t do that for long now! There are .NET technologies such as WCF that are likely to become a must on any line of business, and failing to support them makes your application hopelessly outdated. Delphi was a great tool that opened new perspectives for application development and influenced .NET and C# more than is generally known. The best way to pay homage to Delphi is to give Delphi applications an honorable old age and a chance to be reborn as .NET applications.

抱歉!评论已关闭.