<iframe align="top" marginwidth="0" marginheight="0" src="http://www.zealware.com/46860.html" frameborder="0" width="468" scrolling="no" height="60"></iframe>
看一下如下代码:
[Guid("25088995-7924-4B15-B01A-EA7C422ADC68")] public class CHelloClass : IHello { [DispId(1)] [MethodImplAttribute(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] public extern void HelloWorld(); } class Program { static void Main(string[] args) { CHelloClass obj = new CHelloClass(); obj.HelloWorld(); } } |
这里的CHelloClass是一个COM对象,指定了GUID,实现了IHello接口的HelloWorld函数。然而,当执行这条语句CHelloClass obj = new CHelloClass,会产生如下异常:
Unhandled Exception: System.Security.SecurityException: ECall methods must be packaged into a system module. |
这里异常信息需要解释一下:ECall是一种内部调用的方式(还存在其它方式如FCall等),由CLR本身实现,而不由用户提供实现。当CHelloClass中缺少ComImportAttrib这个属性的时候,CLR会认为HelloWorld这个函数是在CLR本身实现的,然后又在CLR内部的调用表(这个表维护所有CLR内部调用的函数)无法查到对应的实现,所以才抛出异常。当ComImportAttribute存在的时候,CLR才知道这个class是从COM对象Import过来的,从而作一些特殊处理,并不会对HelloWorld按照ECall方式来处理。
我们再看一下,是否MethodImplAttribute这里真正需要呢?可以试一下加上ComImport然后去掉MethodImplAttri看看:
[ComImport] [Guid("25088995-7924-4B15-B01A-EA7C422ADC68")] public class CHelloClass : IHello { [DispId(1)] public extern void HelloWorld(); } class Program { static void Main(string[] args) { CHelloClass obj = new CHelloClass(); obj.HelloWorld(); } } |
当到了new CHelloClass这条语句的时候,会产生下面异常:
Unhandled Exception: System.TypeLoadException: Could not load type 'CHelloClass' from assembly 'Program, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' because the method 'HelloWorld' has no implementation (no RVA). at Program.Main(String[] args) |
这一次,CLR则报告HelloWorld函数没有对应的实现代码。没有RVA的意思是CLR无法找到HelloWorld函数代码的位置。这个位置是一个内存的相对位置,因此称之为RVA(Relative Virtual Address)。由于实际的实现是由CLR提供,准确说是RCW提供,因此这里是需要MethodImplAttrbute的。
最终正确的版本如下:
[ComImport] [Guid("25088995-7924-4B15-B01A-EA7C422ADC68")] public class CHelloClass : IHello { [DispId(1)] [MethodImplAttribute(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] public extern void HelloWorld(); } class Program { static void Main(string[] args) { CHelloClass obj = new CHelloClass(); obj.HelloWorld(); } } |
当然了,如果你不自己编写COM Wrapper代码的话则不会遇到类似的问题。所以请尽可能的让Tlbimp替你生成Interop代码,而不是自己手动编写,除非Tlbimpl生成的代码不符合你的要求。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1608022
分享到:
相关推荐
根据SQLServer数据表生成C#实体类,内含SQLHelper,生成工具及源码。可生成数据库图片存储的字段
SqlServer数据库表生成C# Model实体类 小工具 TableToModel源码 具体讲解:https://blog.csdn.net/weixin_38211198/article/details/91127595
可以自动于sql数据库连接,分析数据库表,并自动生成实体类,减少写实体类的时间
这个只是一个小工具,快速生成实体类。程序难免有些许问题。
一个C#实体类生成器,有源码。可以自动生成C#的实体类,解决VS只能一个字段一个字段的封装的弊端。
根据xml文件生成C# 属性class类,附件含源码。分享给需要的朋友
该工具支持通过在软件界面输入或者粘贴JSON字符串,根据字符串生成C#编程开发使用的JSON实体类文件。
可以通过SQLserver生成或者批量导出实体类,非常方便 C#根据SQLserver生成实体类 工具-源码
将C# 类文件中属性和方法自动生成文档,C#类文档结构化生成
一个非常好用的 XML 文件生成类。提供快捷的产生 XML 文件的众多方法。(C# )
超好用的实体类生成工具,比其他实体类生成工具都全面,支持检索表名,支持批量生成等功能。
狂人代码生成器 可以自动生成实体类、数据访问层码、业务逻辑层 源代码。经典三层架构 项目源码 、 能自动生成解决方案,支持 Visual Studio 2005 和 Visual Studio 2005 !
支持实体类生成程序:C# 和 java *注意: 电脑上一定要安装 framework才能运行本软件 有什么问题请联系qq:910579826 备注添加:实体类生成器 1. 用户首先选择要操作的数据库,选中后程序会自动创建数据库连接字符...
protobuf 自动生成c# .cs文件。。。内附使用说明。protobuf 自动生成c# .cs文件。。。内附使用说明。
通过xsd产生C#实体类解析XML或生成XML,有疑问请私聊
C#生成二维码和条码类源码,BarCodeHelper.cs,QRCodeHelper.cs
手动生成WSDL.exe代理类,简单操作容易上手
使用c#代码生成Excel的类,支持字体等格式、公式。 生成的文件为xml类型。使用者无需安装Excel或者使用DLL
C#使用实体类生成数据库表,linq使用示例代码