1. Technology
The CodeDOM and the Delphi for .NET IDE
The last part of the CodeDOM story explains the features behind the DelphiProvider assembly - a CodeDomProvider specially designed for Delphi developers.
 Win prizes by sharing code!
Do you have some Delphi code you want to share? Are you interested in winning a prize for your work?
Delphi Programming Quickies Contest
 More of this Feature
• Part 1: CodeDOM basics
• Part 2: Creating a CodeDOM in Delphi Code

• DOWNLOAD SAMPLE PROJECTS
 Join the Discussion
"Post your views, comments, questions and doubts to this article."
Discuss!
 Related Resources
• Delphi for .NET topics

Article originally written by Corbin Dunn (Borland R&D Software Engineer).

First part of this article explained what is CodeDOM. The CodeDOM is a collection of classes used to represent source code. Once source code is represented in a CodeDOM, it can then be printed, compiled to an assembly, or compiled to memory and executed. The second part showed how to use CodeDOM with Delphi code.

The CodeDOM and Delphi The DelphiProvider
The CodeDomProvider is the base factory class that provides a way of accessing an ICodeCompiler and ICodeGenerator. This allows you to respectively compile and print code in a particular language.

The .NET Framework includes generators for C#, VB, and Java (MS style). To use the C# or VB one, all you have to do is use the Microsoft.CSharp or Microsoft.VisualBasic namespace. To use the Java one, you must use Microsoft.VJSharp and reference the assembly VJSharpCodeProvider.dll.

Borland has provided a CodeDomProvider to use for Delphi. To use it, you must reference the assembly DelphiProvider.dll and use the namespace Borland.Delphi.

WinForms/WebForms Only?
One thing to be aware of is that the CodeDOM is available for general VCL for .NET development, and not just WinForms or WebForms. Since the CodeDOM classes and interfaces are in the base .NET Framework Class Library (FCL), one can easily use them at anytime, without any dependency on System.Windows.Forms.dll.

Using the OpenTools API to access the CodeDOM
You can create an OpenTools API (OTA) plug-in that utilizes the Delphi and C# CodeDOM’s from inside the BDS IDE.

Look at the sample project for the implementation details of exactly how to create an OTA plug-in, if you are not familiar with how to do so.

To install the plug-in into the IDE, start regedit, and add a string value under the key at: HKCU\Software\Borland\BDS\(your version)\ Known IDE Assemblies

Set the Name to your plug in assembly’s location (ie: $(BDS)\bin\MyPlugin.dll) and set the value to anything but an empty string (ie: "My IDE Assembly").

Reading the CodeDOM
Only can only get a DOM from files that are open in the IDE. But, don’t worry, it is possible to open files using the IOTAModuleService. An opened file in the IDE is represented by an IOTAModule.

Once you have an IOTAModule, you can query for the IOTACodeDomProvider interface:

var
  CurrentModule: IOTAModule;
  Provider: IOTACodeDomProvider;
  DomFile: IOTACodeDomFile;
begin
  CurrentModule := BorlandIDE.ModuleServices.CurrentModule;
  Provider := IOTACodeDomProvider(
              CurrentModule.GetService(
              typeof(IOTACodeDomProvider)));

If the module doesn’t support a CodeDOM, it will return nil. After you have the provider, you can access the IOTACodeDomFile from it. It is always good to check for nil in this case too:

  if Provider <> nil then
  begin
    DomFile := Provider.CodeDomFile;
    if DomFile <> nil then
      ... // Do something with the DomFile
  end;

Once you have an IOTACodeDomFile, you can finally get a CodeDOM:

  MyCompileUnit := CodeCompileUnit(DomFile.GetDom);

It is that easy! You can now do things, like walk all the namespaces and types in that CodeDOM, doing whatever operations you want to it.

Browsing the CodeDOM
Let’s say that you want to know what line and column a particular CodeMemberMethod is. That’s easy; you can use the CodeTypeMember.LinePragma property. But, an examination of the CodeLinePragma type reveals that it only has the FileName and LinNumber for the given member; there is no column information!

To handle this situation, BDS produced CodeDOM’s have special UserData added to the CodeObject.UserData property. If you access CodeMemberMethod.UserData[‘Line’] and CodeMemberMethod.UsetData[‘Col’] you can get the line and column of a method’s implementation body! This is how the IDE finds where to go when you add a new method with the WindowsForms designer.

Committing Changes
Once you have made some changes to the CodeDOM, you will probably want to commit those changes back to source code in the IDE. You can easily do this with the IOTACodeDomFile.WriteDom(...) method. The first parameter to WriteDom is the DOM you want to commit. The second parameter is the formatting options you want to use; if you pass nil, the default IDE options will be used.

Important notes

There are several things to be aware of when using a CodeDOM from inside the IDE:

  • You can only update entire methods; you cannot update individual statements or expressions.
  • Things which can’t be represented in the CodeDOM are ignored (ie: global procedures)
  • The Delphi CodeDOM can only ever contain one namespace. Attempting to add another namespace to it will be ignored.
  • When committing a CodeDOM to the IDE, the underlying source code cannot have had changes made to it since you requested the CodeDOM. It is best to always grab a fresh CodeDOM from the IOTACodeDomFile, make your changes, and then immediately commit the changes to the IOTACodeDomFile.

    Conclusion
    Well, that’s it! You should now have the knowledge of how to leverage the ultimate power of the CodeDOM.

    Be sure to take a look at the example code for a tutorial of how to use the CodeDOM; both from a stand alone application, and an IDE plug-in wizard.

    First part > The Code Document Object Model (CodeDOM) basics > Part 1, 2, 3

  • ©2014 About.com. All rights reserved.