http://www.developer.com/net/article.php/3842541/Improved-COM-Interoperability.htm
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. 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. 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. In order to allow for any and all parameters to be optional, the concept of named parameters goes hand-in-hand. 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. 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. 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. The following code has been revised to rely on the object binder to do the mapping: With the next release of the .NET Framework you will be able to omit the "ref" keyword in some cases when talking to COM. 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. 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. 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. 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.
Improved COM Interoperability
October 26, 2009
Introduction
Optional and Named Parameters
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);
// 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);
// 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); 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);
doc.SaveAs("Test.docx");Automatic Object to Dynamic Mapping
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); //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
Interop Type Embedding ("No PIA")
Summary
Future Columns
About the Author