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

发布于 2024-07-11 19:13:19 字数 1692 浏览 6 评论 0原文


问题

我的问题是:C# 本身支持后期绑定 IDispatch 吗?


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

在 .NET 世界中,如果安装了 Office 2000 进行开发,则从现在到世界末日,每个开发人员和每个客户都需要拥有 Office 2000。

在 .NET 之前的世界中,我们使用 COM

例如:

1) 使用与版本无关的 ProgID

"Excel.Application"

,它解析为:

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

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

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

现在我们开始比赛了 - 能够从我的内部使用 Excel应用。 当然,如果您真的想使用该对象,则必须调用某种调用方法的方式。

我们可以获得各种接口声明,并翻译成我们的语言。 这种技术很好,因为我们可以进行

  • 早期绑定
  • 代码洞察
  • 编译类型语法检查

,并且一些示例代码可能是:

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

但是使用接口有一个缺点:我们必须掌握各种接口声明,并将其翻译成我们的语言。 我们被困于使用基于方法的调用,必须指定所有参数,例如:

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

在现实世界中,这已被证明具有我们愿意放弃的缺点:

  • 早期绑定
  • 代码洞察
  • 编译时语法检查

,而不是使用IDispatch后期绑定:

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

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

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


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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

也只是曾经 2024-07-18 19:13:19

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

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

下面是一些使用 Excel 的示例。 这样你就不需要添加对 Microsoft 臃肿的 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 );

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 );
梦回梦里 2024-07-18 19:13:19

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

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

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.

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.

岁吢 2024-07-18 19:13:19

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

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

C# 4's dynamic keyword supports IDispatch and late binding. You can read Sam Ng's dynamic series for more information

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.

祁梦 2024-07-18 19:13:19

正如其他人所说 - 使用 c#4 的“dynamic”关键字很酷。 这是一个简单的例子 - 它比使用“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"
}

As others have said - using c#4's "dynamic" keyword rocks. Here's a simple example - it so much more succint than using "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"
}
扬花落满肩 2024-07-18 19:13:19

如果您花时间编写接口,也许您可​​以在 C# 2.0/3.0 中编写更好的代码
包含您想要的对象的方法和属性并添加一些属性(我从内存中编写它,所以细节可能不正确,但我发誓它对我有用......)

    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
    }

如上所述,代码将无法正常工作框,它更多的是提示在 msdn 中挖掘什么。

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.

于我来说 2024-07-18 19:13:19

你好,哥们儿,
我目前有 2 个 Codeplex 项目来解决这个问题。

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

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

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

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

the second one is a CodeGenerator http://latebindingapi.codeplex.com
the 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文