| More
All posts tagged 'com interop'
 


Simple COM Interop with Dynamic

The C# 2010 dynamic keyword can be used for a variety of reasons, some of which are a tad esoteric.  However, there is a very practical use of this new language feature, specifically the (radical) simplification of COM interop programming. By default, when you import a COM library into a VS 2010 project (configured to target .NET 4.0), every COM VARIANT is automatically mapped to a dynamic data type.

This behavior greatly decreases the need to cast data types and drill into low level interop primitives (such as the underlying get_ / set_ methods).

Furthermore, thanks to C# 2010 optional arguments, you no longer need to author reams of Type.Missing tokens when specifying missing values.

To showcase the distinction, assume you wish to map some data in a List to Microsoft Excel.  Before .NET 4.0, you might author code such as the following:

Code Snippet
  1. static void ExportToExcel2008(List<Car> carsInStock)
  2. {
  3.     Excel.Application excelApp = new Excel.Application();
  4.  
  5.     // Must mark missing params!
  6.     excelApp.Workbooks.Add(Type.Missing);
  7.  
  8.     // Must cast Object as _Worksheet!
  9.     Excel._Worksheet workSheet = (Excel._Worksheet)excelApp.ActiveSheet;
  10.  
  11.     // Must cast each Object as Range object then call
  12.     // call low level Value2 property!
  13.     ((Excel.Range)excelApp.Cells[1, "A"]).Value2 = "Make";
  14.     ((Excel.Range)excelApp.Cells[1, "B"]).Value2 = "Color";
  15.     ((Excel.Range)excelApp.Cells[1, "C"]).Value2 = "Pet Name";
  16.  
  17.     int row = 1;
  18.     foreach (Car c in carsInStock)
  19.     {
  20.         row++;
  21.         // Must cast each Object as Range and call low level Value2 prop!
  22.         ((Excel.Range)workSheet.Cells[row, "A"]).Value2 = c.Make;
  23.         ((Excel.Range)workSheet.Cells[row, "B"]).Value2 = c.Color;
  24.         ((Excel.Range)workSheet.Cells[row, "C"]).Value2 = c.PetName;
  25.     }
  26.  
  27.     // Must call get_Range method and then specify all missing args!.
  28.     excelApp.get_Range("A1", Type.Missing).AutoFormat(Excel.XlRangeAutoFormat.xlRangeAutoFormatClassic2,
  29.             Type.Missing, Type.Missing, Type.Missing,
  30.             Type.Missing, Type.Missing, Type.Missing);
  31.  
  32.     // Must specify all missing optional args!  
  33.     workSheet.SaveAs(string.Format(@"{0}\Inventory.xlsx", Environment.CurrentDirectory),
  34.         Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
  35.         Type.Missing, Type.Missing, Type.Missing);
  36.     excelApp.Quit();
  37.     MessageBox.Show("The Inventory.xslx file has been saved to your app folder", "Export complete!");
  38. }

Notice in particular the grimy casting operations (Excel.Range, and so forth). 

Now, here is the same code once again, using the new features of C# 2010:

Code Snippet
  1. static void ExportToExcel(List<Car> carsInStock)
  2. {
  3.     // Load up Excel, then make a new empty workbook.
  4.     Excel.Application excelApp = new Excel.Application();
  5.     excelApp.Workbooks.Add();
  6.  
  7.     // This example uses a single workSheet.
  8.     Excel._Worksheet workSheet = excelApp.ActiveSheet;
  9.  
  10.     // Establish column headings in cells.
  11.     workSheet.Cells[1, "A"] = "Make";
  12.     workSheet.Cells[1, "B"] = "Color";
  13.     workSheet.Cells[1, "C"] = "Pet Name";
  14.  
  15.     // Now, map all data in List<Car> to the cells of the spread sheet.
  16.     int row = 1;
  17.     foreach (Car c in carsInStock)
  18.     {
  19.         row++;
  20.         workSheet.Cells[row, "A"] = c.Make;
  21.         workSheet.Cells[row, "B"] = c.Color;
  22.         workSheet.Cells[row, "C"] = c.PetName;
  23.     }
  24.  
  25.     // Give our table data a nice look and feel.
  26.     workSheet.Range["A1"].AutoFormat(
  27.         Excel.XlRangeAutoFormat.xlRangeAutoFormatClassic2);
  28.  
  29.     // Save the file, quit Excel and display message to user.
  30.     workSheet.SaveAs(string.Format(@"{0}\Inventory.xlsx", Environment.CurrentDirectory));
  31.     excelApp.Quit();
  32.     MessageBox.Show("The Inventory.xslx file has been saved to your app folder", "Export complete!");
  33. }

Nice, eh? I'm sure you'd agree that simplification is always a good thing...


Posted by: Andrew Troelsen
Posted on: 5/16/2010 at 8:59 PM
Tags:
Categories: .NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed