Ian*_*oyd 27 c# late-binding idispatch
我的问题是:C#nativly支持后期绑定IDispatch吗?
假装我正在尝试自动化Office,同时兼容客户安装的任何版本.
在.NET世界中,如果您安装了Office 2000,那么从现在到结束,每个开发人员和每个客户都需要拥有Office 2000.
在.NET之前的世界中,我们使用COM与Office应用程序进行通信.
例如:
1)使用版本独立的ProgID
"Excel.Application"
Run Code Online (Sandbox Code Playgroud)
解析为:
clsid = {00024500-0000-0000-C000-000000000046}
Run Code Online (Sandbox Code Playgroud)
然后使用COM,我们要求将其中一个类实例化为一个对象:
IUnknown unk;
CoCreateInstance(
clsid,
null,
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
IUnknown,
out unk);
Run Code Online (Sandbox Code Playgroud)
现在我们即将参加比赛 - 能够在我的应用程序中使用Excel.当然,如果你真的想要使用该对象,你必须调用一些方法来调用方法.
我们可以得到阿霍德不同的接口声明,翻译成我们的语言.这项技术很好,因为我们得到了
一些示例代码可能是:
Application xl = (IExcelApplication)unk;
ExcelWorkbook workbook = xl.Workbooks.Add(template, lcid);
Worksheet worksheet = workbook.ActiveSheet;
Run Code Online (Sandbox Code Playgroud)
但是使用接口有一个缺点:我们必须得到各种接口声明,转换成我们的语言.我们坚持使用基于方法的调用,必须指定所有参数,例如:
ExcelWorkbook workbook = xl.Workbooks.Add(template, lcid);
xl.Worksheets.Add(before, after, count, type, lcid);
Run Code Online (Sandbox Code Playgroud)
在现实世界中,这证明了我们愿意放弃的这些缺点:
而是使用IDispatch后期绑定:
Variant xl = (IDispatch)unk;
Variant newWorksheet = xl.Worksheets.Add();
Run Code Online (Sandbox Code Playgroud)
因为Excel自动化是为VB脚本设计的,所以即使没有它们也没有过载,也可以省略很多参数.
注意:不要混淆我的Excel示例以及我想使用IDispatch的原因.并非每个COM对象都是Excel.某些COM对象除了通过IDispatch之外没有任何支持.
Ian*_*oyd 26
相对而言,您可以在C#中使用后期绑定IDispatch绑定.
http://support.microsoft.com/kb/302902
这是使用Excel的一些示例.这样你就不需要在微软臃肿的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 );
Run Code Online (Sandbox Code Playgroud)
你必须等待C#4.0出来才能获得你想要的后期绑定.每当我需要互操作能力时,我都会切换回VB.Net模式,这样我就可以利用C#似乎缺乏的COM功能.
我使用的简单方法是在VB.Net中创建一个类,它执行IDispatch工作,然后公开我想用作包装器方法的方法,然后我可以从我的C#代码中随意调用它们.不是最优雅的解决方案,但它在过去的几个月里让我脱离了一两个.