November 1, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Improved COM Interoperability

  • October 26, 2009
  • By Mark Strawmyer
  • Send Email »
  • More Articles »

Introduction

Welcome to this installment of the .NET Nuts & Bolts column. The prior article focused on the future direction of managed languages and introduced trends that are influencing the future of C# and Visual Basic. It introduced the Dynamic Language Runtime (DLR) and touched ever so briefly on the improved COM interoperability that is coming along with that. This article will build on that and provide specifics.

Optional and Named Parameters

Traditionally C# has avoided the implementation of optional and named parameters. The thought process being that overloading could provide much of what was necessary. The following example demonstrates sample method footprints for a method to open a text file and several overloads for it.

  public StreamReader OpenTextFile(      string path,      Encoding encoding,      bool detectEncoding,      int bufferSize);     public StreamReader OpenTextFile(      string path,      Encoding encoding,      bool detectEncoding);    public StreamReader OpenTextFile(      string path,      Encoding encoding);    public StreamReader OpenTextFile(string path);

However, with the commitment to co-evolution between C# and Visual Basic it is necessary for C# to join with the ranks of VB and support optional and named parameters. The revised example using optional parameters is below. This creates the ability to vary the method calls with only a single definition.

  // With optional parameters  public StreamReader OpenTextFile(      string path,      Encoding encoding = null,      bool detectEncoding = true,      int bufferSize = 1024);     // Method call excluding the last two parameters  OpenTextFile("foo.txt", Encoding.UTF8);

In order to allow for any and all parameters to be optional, the concept of named parameters goes hand-in-hand.

  • Named arguments can appear in any order as long as all names are given
  • Named arguments must be last in the list of parameters if not all parameters are named
  • Arguments are evaluated in the order given
  • Non-optional parameters must always be specified

  // Uses a named argument in last position  OpenTextFile("foo.txt", Encoding.UTF8, bufferSize: 4096);    // Uses named parameters to reorder the parameters and leave one out  OpenTextFile(      bufferSize: 4096,      path: "foo.txt",      detectEncoding: false);

Optional and named parameters have a direct benefit to COM Interoperability. The following example represents code that would previously have been required to create and save a Word document.

  object fileName = "Test.docx";  object missing  = System.Reflection.Missing.Value;  doc.SaveAs(ref fileName,      ref missing, ref missing, ref missing,      ref missing, ref missing, ref missing,      ref missing, ref missing, ref missing,      ref missing, ref missing, ref missing,      ref missing, ref missing, ref missing);

With optional and named parameters, the above example can be heavily simplified to the simple code below, which results in Office automation and other code finally looking the way it was intended to look.

  doc.SaveAs("Test.docx");

Automatic Object to Dynamic Mapping

The Dynamic Language Runtime (DLR) introduces the concept of object binders. By default the DLR includes a COM binder that maps dynamic types to statically typed .NET objects. The following sample code shows a snippet of code that is part of reading all of the processes on the local machine and then graphing resources in Excel. Note the heavy use of casting within the code and how it makes the code much more complicated to read.

  xl.Workbooks.Add(Type.Missing);  xl.Visible = true;    ((Excel.Range)xl.Cells[1, 1]).Value2 = "Process Name";  ((Excel.Range)xl.Cells[1, 2]).Value2 = "Memory Usage";    int i = 2;  foreach (var proc in (from p in Process.GetProcesses()                           orderby p.VirtualMemorySize64 descending                                    select p).Take(20))  {              ((Excel.Range)xl.Cells[i, 1]).Value2 = proc.ProcessName;              ((Excel.Range)xl.Cells[i, 2]).Value2 = proc.VirtualMemorySize64;              i++;  }    Excel.Range cellRange = (Excel.Range)xl.Cells[1, 1];    Excel.Chart xlChart = (Excel.Chart)xl.ActiveWorkbook.Charts.  Add(Type.Missing, xl.ActiveSheet, Type.Missing, Type.Missing);

The following code has been revised to rely on the object binder to do the mapping:

  //Optional parameters   xl.Workbooks.Add();  xl.Visible = true;    //Automatic conversion into dynamic  xl.Cells[1, 1].Value2 = "Process Name";  xl.Cells[1, 2].Value2 = "Memory Usage";    int i = 2;  foreach (var proc in (from p in Process.GetProcesses()                                    orderby p.VirtualMemorySize64 descending                                    select p).Take(20))  {              //Automatic conversion into dynamic              xl.Cells[i, 1].Value2 = proc.ProcessName;              xl.Cells[i, 2].Value2 = proc.VirtualMemorySize64;              i++;  }    //Equality Conversion  Excel.Range cellRange = xl.Cells[1, 1];    //Equality Conversion + Named Parameters + Optional Parameters  Excel.Chart xlChart = xl.ActiveWorkbook.Charts.Add(After:xl.ActiveSheet);

Optional "ref" Modifier

With the next release of the .NET Framework you will be able to omit the "ref" keyword in some cases when talking to COM.

Interop Type Embedding ("No PIA")

Another feature being introduced that will yield COM Interoperability improvements has to do with not requiring the primary interop assembly (PIA). Traditionally there would have been a number of additional DLLs you would have had to deploy with your application to support specialized types. These types can be embedded directly in to the application now, which means you don't need the primary assembly at all to utilize these types.

Summary

You have now seen some of the COM interoperability improvements that are coming along with the DLR such as optional and named parameters. The introduction of this functionality should make COM Interop code not only easier to write, but also to read and maintain in the long run.

Future Columns

The topic of the next column is likely to be more on the benefits coming with .NET Framework 4.0. If you have something else in particular that you would like to see explained here you could reach me at mark.strawmyer@crowehorwath.com.

About the Author

Mark Strawmyer is a Senior Architect of .NET applications for large and mid-size organizations. He specializes in architecture, design and development of Microsoft-based solutions. Mark was honored to be named a Microsoft MVP for application development with C# for the fifth year in a row. You can reach Mark at mark.strawmyer@crowehorwath.com.






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel