C# .NET 是否支持 IDispatch 后期绑定?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/403218/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 02:06:54  来源:igfitidea点击:

Does C# .NET support IDispatch late binding?

c#late-bindingidispatch

提问by Ian Boyd



The Question

问题

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

我的问题是:C# 是否原生支持后期绑定 IDispatch?



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

假设我正在尝试自动化 Office,同时与客户安装的任何版本兼容。

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.

在 .NET 世界中,如果您在安装了 Office 2000 的情况下进行开发,那么从现在到结束,每个开发人员和每个客户都需要安装 Office 2000。

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

在 .NET 出现之前,我们使用COM与 Office 应用程序对话。

For example:

例如:

1) Use the version independant ProgID

1) 使用与版本无关的 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:

然后使用 COM,我们要求将这些类之一实例化为一个对象:

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 reallyyou want to use the object, you have to call have some way of calling methods.

现在我们开始比赛 - 能够在我的应用程序中使用 Excel。当然,如果真的要使用对象,则必须调用有某种调用方法。

We couldget ahold of the various interfacedeclarations, 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 IDispatchlate binding:

而是使用IDispatch后期绑定:

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.

因为 Excel 自动化是为 VB 脚本设计的,所以可以省略很多参数,即使没有它们就没有过载。

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.

注意:不要将我的 Excel 示例与我想使用 IDispatch 的原因混淆。并非每个 COM 对象都是 Excel。除了通过 IDispatch 之外,某些 COM 对象没有其他支持。

采纳答案by Ian Boyd

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

相对而言,您可以在 C# 中使用后期绑定 IDispatch 绑定。

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

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:

这是使用 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 );

回答by configurator

C# 4's dynamickeyword supports IDispatch and late binding. You can read Sam Ng's dynamic seriesfor more information

C# 4 的dynamic关键字支持 IDispatch 和后期绑定。您可以阅读 Sam Ng 的动态系列了解更多信息

Oh, and C# 4 is only available as a CTP today. You'll have to either wait for Visual Studio vNext or use the beta (which runs on a Windows Server 2008 Virtual PC) to use that.

哦,C# 4 目前仅作为 CTP 提供。您必须等待 Visual Studio vNext 或使用测试版(在 Windows Server 2008 Virtual PC 上运行)才能使用它。

回答by thaBadDawg

You gotta wait for C# 4.0 to come out to get the late binding that you are looking for. Any time I need interop capabilities I switch back to VB.Net mode so I can take advantage of the COM capabilities that C# seems to lack.

您必须等待 C# 4.0 出来才能获得您正在寻找的后期绑定。任何时候我需要互操作功能时,我都会切换回 VB.Net 模式,这样我就可以利用 C# 似乎缺乏的 COM 功能。

The simple method that I use is creating a class in VB.Net that does the IDispatch work and then exposing the methods that I want to use as methods of my wrapper and then I can call them at will from my C# code. Not the most elegant of solutions, but it has gotten me out of a jam or two over the past few months.

我使用的简单方法是在 VB.Net 中创建一个类来执行 IDispatch 工作,然后公开我想用作包装器方法的方法,然后我可以从我的 C# 代码中随意调用它们。不是最优雅的解决方案,但在过去的几个月里,它让我摆脱了一两次困境。

回答by Thomas

probably you can get away with much nicer code in in C# 2.0/3.0 if you take the time to write an interface containing the methods and properties you want of the object and add some attributes (i write it from memory, so details may not be correct, but i swear it worked for me...)

如果您花时间编写包含对象所需方法和属性的接口并添加一些属性(我是从内存中编写的,因此细节可能不是正确,但我发誓它对我有用......)

    using System.Runtime.Interopservices;

    [Guid("00024500-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    interface IExcel
    {
      // sample property
      string Name{get;}
      // more properties
    }

    // and somewhere else
    void main()
    {
      Object xl = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
      IExcel excel = (IExcel)xl;
      string name = xl.name
    }

As mentioned, the code will not work out of the box, it is more a hint what to dig for in msdn.

如前所述,该代码无法立即使用,更多的是提示在 msdn 中挖掘什么。

回答by Homero

hey Dude, i have 2 codeplex projects currently to resolve this problem.

嘿伙计,我目前有 2 个 codeplex 项目来解决这个问题。

the first one is LateBindingApi.Excel http://excel.codeplex.commapped latebinded invoke call to the well known object model. this was a test project for the following project.

第一个是 LateBindingApi.Excel http://excel.codeplex.com映射到众所周知的对象模型的后期绑定调用。这是以下项目的测试项目。

the second one is a CodeGenerator http://latebindingapi.codeplex.comthe tool creates c# projects from COM Type libraries. the generated projects includes mapper objects with latebind accessing the COM Server. the highlight is the tool converts COM type libs in different versions to one single project(for example excel 9,10,11) and marked all entities with an self defined SupportByLibrary Attribut. i have analyzed all office apps in version 9,10,11,12,14 with this this tool now and generate a c# solution, its available as tested beta with sample code on main page.

第二个是 CodeGenerator http://latebindingapi.codeplex.com该工具从 COM 类型库创建 c# 项目。生成的项目包括具有后期绑定访问 COM 服务器的映射器对象。亮点是该工具将不同版本的 COM 类型库转换为单个项目(例如 excel 9、10、11),并使用自定义的 SupportByLibrary 属性标记所有实体。我现在已经使用此工具分析了版本 9、10、11、12、14 中的所有办公应用程序,并生成了 ac# 解决方案,它已作为测试版提供,并在主页上提供示例代码。

回答by Grynn

As others have said - using c#4's "dynamic" keyword rocks. Here's a simple example - it so much more succint than using "InvokeMethod"

正如其他人所说 - 使用 c#4 的“动态”关键字摇滚。这是一个简单的例子 - 它比使用“InvokeMethod”简洁得多

dynamic xl = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
dynamic books = xl.Workbooks;
dynamic book = books.Add();

Console.WriteLine(books.Count);     //Writes 1

foreach (dynamic b in books)        
{
Console.WriteLine(b.Name);      //Writes "Book1"
}