C# 4.0: COM Interop Improvements
- by Paulo Morgado
Dynamic resolution as well as named and optional arguments greatly improve the experience of interoperating with COM APIs such as Office Automation Primary Interop Assemblies (PIAs). But, in order to alleviate even more COM Interop development, a few COM-specific features were also added to C# 4.0. Ommiting ref Because of a different programming model, many COM APIs contain a lot of reference parameters. These parameters are typically not meant to mutate a passed-in argument, but are simply another way of passing value parameters. Specifically for COM methods, the compiler allows to declare the method call passing the arguments by value and will automatically generate the necessary temporary variables to hold the values in order to pass them by reference and will discard their values after the call returns. From the point of view of the programmer, the arguments are being passed by value. This method call: object fileName = "Test.docx";
object missing = Missing.Value;
document.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);
can now be written like this:
document.SaveAs("Test.docx",
Missing.Value, Missing.Value, Missing.Value,
Missing.Value, Missing.Value, Missing.Value,
Missing.Value, Missing.Value, Missing.Value,
Missing.Value, Missing.Value, Missing.Value,
Missing.Value, Missing.Value, Missing.Value);
And because all parameters that are receiving the Missing.Value value have that value as its default value, the declaration of the method call can even be reduced to this:
document.SaveAs("Test.docx");
Dynamic Import
Many COM methods accept and return variant types, which are represented in the PIAs as object. In the vast majority of cases, a programmer calling these methods already knows the static type of a returned object form the context of the call, but has to explicitly perform a cast on the returned values to make use of that knowledge. These casts are so common that they constitute a major nuisance.
To make the developer’s life easier, it is now possible to import the COM APIs in such a way that variants are instead represented using the type dynamic which means that COM signatures have now occurrences of dynamic instead of object.
This means that members of a returned object can now be easily accessed or assigned into a strongly typed variable without having to cast.
Instead of this code:
((Excel.Range)(excel.Cells[1, 1])).Value2 = "Hello World!";
this code can now be used:
excel.Cells[1, 1] = "Hello World!";
And instead of this:
Excel.Range range = (Excel.Range)(excel.Cells[1, 1]);
this can be used:
Excel.Range range = excel.Cells[1, 1];
Indexed And Default Properties
A few COM interface features are still not available in C#. On the top of the list are indexed properties and default properties. As mentioned above, these will be possible if the COM interface is accessed dynamically, but will not be recognized by statically typed C# code.
No PIAs – Type Equivalence And Type Embedding
For assemblies indentified with PrimaryInteropAssemblyAttribute, the compiler will create equivalent types (interfaces, structs, enumerations and delegates) and embed them in the generated assembly.
To reduce the final size of the generated assembly, only the used types and their used members will be generated and embedded.
Although this makes development and deployment of applications using the COM components easier because there’s no need to deploy the PIAs, COM component developers are still required to build the PIAs.