Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C# .NET support IDispatch late binding?


The Question

My question is: Does C# nativly support late-binding IDispatch?


Pretend i'm trying to automate Office, while being compatible with whatever version the customer has installed.

In the .NET world if you developed with Office 2000 installed, every developer, and every customer, from now until the end of time, is required to have Office 2000.

In the world before .NET, we used COM to talk to Office applications.

For example:

1) Use the version independant ProgID

"Excel.Application" 

which resolves to:

clsid = {00024500-0000-0000-C000-000000000046} 

and then using COM, we ask for one of these classes to be instantiated into an object:

IUnknown unk; CoCreateInstance(     clsid,      null,     CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,     IUnknown,      out unk); 

And now we're off to the races - able to use Excel from inside my application. Of course, if really you want to use the object, you have to call have some way of calling methods.

We could get ahold of the various interface declarations, translated into our language. This technique is good because we get

  • early binding
  • code-insight
  • compile type syntax checking

and some example code might be:

Application xl = (IExcelApplication)unk; ExcelWorkbook workbook = xl.Workbooks.Add(template, lcid); Worksheet worksheet = workbook.ActiveSheet; 

But there is a downside of using interfaces: we have to get ahold of the various interface declarations, transated into our language. And we're stuck using method-based invocations, having to specify all parameters, e.g.:

ExcelWorkbook workbook = xl.Workbooks.Add(template, lcid); xl.Worksheets.Add(before, after, count, type, lcid); 

This has proved, in the real world, to have such downsides that we would willingly give up:

  • early binding
  • code-insight
  • compile time syntax checking

and instead use IDispatch late binding:

Variant xl = (IDispatch)unk; Variant newWorksheet = xl.Worksheets.Add(); 

Because Excel automation was designed for VB Script, a lot of parameters can be ommitted, even when there is no overload without them.

Note: Don't confuse my example of Excel with a reason of why i want to use IDispatch. Not every COM object is Excel. Some COM objects have no support other than through IDispatch.

like image 567
Ian Boyd Avatar asked Dec 31 '08 15:12

Ian Boyd


People also ask

Does C have do-while?

The C do while statement creates a structured loop that executes as long as a specified condition is true at the end of each pass through the loop.

Does hep C go away?

It is highly curable ... Direct-acting antiviral medications — given over a 12-week period — actually can cure early acute hepatitis C better than 90% of the time.

What is || in C programming?

Logical OR operator: || The logical OR operator ( || ) returns the boolean value true if either or both operands is true and returns false otherwise. The operands are implicitly converted to type bool before evaluation, and the result is of type bool .


1 Answers

You can, relativly, use late-binding IDispatch binding in C#.

http://support.microsoft.com/kb/302902

Here's some sample for using Excel. This way you don't need to add a needless dependancy on Microsoft's bloaty PIA:

//Create XL Object xl = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));  //Get the workbooks collection. //   books = xl.Workbooks; Object books = xl.GetType().InvokeMember( "Workbooks",        BindingFlags.GetProperty, null, xl, null);  //Add a new workbook. //   book = books.Add(); Objet book = books.GetType().InvokeMember( "Add",        BindingFlags.InvokeMethod, null, books, null );  //Get the worksheets collection. //   sheets = book.Worksheets; Object sheets = book.GetType().InvokeMember( "Worksheets",       BindingFlags.GetProperty, null, book, null );  Object[] parameters;  //Get the first worksheet. //   sheet = sheets.Item[1] parameters = new Object[1]; parameters[0] = 1; Object sheet = sheets.GetType().InvokeMember( "Item",        BindingFlags.GetProperty, null, sheets, parameters );  //Get a range object that contains cell A1. //   range = sheet.Range["A1]; parameters = new Object[2]; parameters[0] = "A1"; parameters[1] = Missing.Value; Object range = sheet.GetType().InvokeMember( "Range",       BindingFlags.GetProperty, null, sheet, parameters );  //Write "Hello, World!" in cell A1. //   range.Value = "Hello, World!"; parameters = new Object[1]; parameters[0] = "Hello, World!"; objRange_Late.GetType().InvokeMember( "Value", BindingFlags.SetProperty,        null, range, parameters );  //Return control of Excel to the user. //   xl.Visible = true; //   xl.UserControl = true; parameters = new Object[1]; parameters[0] = true; xl.GetType().InvokeMember( "Visible", BindingFlags.SetProperty,       null, xl, Parameters ); xl.GetType().InvokeMember( "UserControl", BindingFlags.SetProperty,       null, xl, Parameters ); 
like image 119
Ian Boyd Avatar answered Sep 19 '22 14:09

Ian Boyd