源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

基于C# 中可以new一个接口?的问题分析

  • 时间:2020-11-01 00:51 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:基于C# 中可以new一个接口?的问题分析
如果有人问你,[b]C# 中可以new 一个接口吗?,你会怎么回答? [/b] 假设ITestInterface 是一个接口,那么这样的代码是否有问题? ITestInterface testInterface = new ITestInterface(); 很多书上都会说,当然有问题,接口不能用new ,然后你就认为上面这句语句肯定通不过编译器的编译了。 可是凡事无绝对,C# 竟然允许你这么写,当然你需要加点”料”才行。 VS2005 中新建控制台程序CA2005.添加 Microsoft.Office.Interop.Excel 引用 [img]http://files.jb51.net/file_images/article/201305/2013051312215353.png[/img] [img]http://files.jb51.net/file_images/article/201305/2013051312215354.png[/img] Program 的Main函数只有一句话: [img]http://files.jb51.net/file_images/article/201305/2013051312215355.png[/img] 注意,可以通过编译,看下Application的定义: [img]http://files.jb51.net/file_images/article/201305/2013051312215356.png[/img] 很明显Application 是个interface, 这里我要扯一下,经常看到有人说string 是类还是结构什么的,看下string 的定义: [img]http://files.jb51.net/file_images/article/201305/2013051312215357.png[/img]  [b]String [/b][b]是用class 来修饰的,所以string 100% 是类。 [/b] 还是扯回来吧,Application 是个接口,但是我们却可以用new  .为什么 先看下反编译后的代码吧: [img]http://files.jb51.net/file_images/article/201305/2013051312215358.png[/img]   可以看到虽然我们写的是new Application,但是编译器为我们生成的却是new ApplicationClass(); 难道Application 有什么特别的地方? 仔细的同学一眼就看出了Application是被这两个特性修饰的: [CoClass(typeof(ApplicationClass))] [Guid("000208D5-0000-0000-C000-000000000046")] 关于CoClass的解释可以看msdn [img]http://files.jb51.net/file_images/article/201305/2013051312215359.png[/img]   有些人不喜欢看msdn,而喜欢看博客的一个原因就是msdn太不直白了。 我个人的理解是CoClass 就好像concrete Class(具体类) 这个特性指示编译器在编译Application的时候,使用ApplicationClass 来实现。 回到上面的最初的问题上: 如何让这段代码通过编译: [b]ITestInterface testInterface = new ITestInterface(); [/b] 通过上面的分析,我们很容易将这个特性来修饰我们的自己的接口: namespace CA2005 {     [CoClass(typeof(TestClass))]     [Guid("6C8BF7FE-1F6B-437E-BCC8-6D2FF04E66B3")]     public interface ITestInterface     {         void DoSomething();     }     [Guid("68C7CB18-0DEE-4689-845D-741525281C76")]     public class TestClass : ITestInterface     {         public void DoSomething()         {             Console.WriteLine("TestClass:DoSomething");         }     }     class Program     {         static void Main(string[] args)         {             Microsoft.Office.Interop.Excel.Application excelApplication =                 new Microsoft.Office.Interop.Excel.Application();             ITestInterface testInterface = new ITestInterface();             testInterface.DoSomething();         }     } } 编译,结果如下: [img]http://files.jb51.net/file_images/article/201305/2013051312215360.png[/img] 接口被标记了CoClassAttribute,而不是ComImportAttribute. [img]http://files.jb51.net/file_images/article/201305/2013051312215361.png[/img] 原来想要new 一个接口使用的是编译器对COM的优化和支持。 很明显上面的Application是一个COM对象,所以可以new Application   ITestApplication中添加ComImportAttribute 特性: [img]http://files.jb51.net/file_images/article/201305/2013051312215362.jpg[/img] 再次运行,结果如下: [img]http://files.jb51.net/file_images/article/201305/2013051312215363.png[/img] 查看下反编译的代码: [img]http://files.jb51.net/file_images/article/201305/2013051312215364.png[/img] 之所以我对VS2005 用红色字体,是因为如果你用VS2010 创建的程序,那么你会看到不一样的反编译结果: public static void [b]Main[/b]() {       Application [b]application1[/b] = (Application) Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("00024500-0000-0000-C000-000000000046")));       ITestInterface [b]interface1[/b] = new TestClass();       interface1.DoSomething();       Console.ReadLine(); } [b]这里的Type.GetTypeFromCLSID 中的guidApplicationClassGuid,也就是CoClassTypeGuid [/b] [ComSourceInterfaces("Microsoft.Office.Interop.Excel.AppEvents")]     [Guid("00024500-0000-0000-C000-000000000046")]     [TypeLibType(2)]     [ClassInterface(0)]     public class ApplicationClass : _Application, Application, AppEvents_Event { } 这点一定要注意。 [b]楼下有些同学说这有什么意义,下面是我的项目实例,也是这个问题才让我研究了这个问题:[/b] 在项目中使用了一种C3读卡器,这种读卡器提供了读卡接口(C3ReadCard),但是开发环境是2005,所以不能够C3ReadCard c3=new C3ReadCard(); 这点很奇怪,Excel的可以new,但是C3ReadCard却不可以new,但是通过反射去调用实现类就可以使用C3ReadCard的接口。 这个问题的意义在于你明白编译器如何去处理new一个接口所生成的代码,也许还有其他的用处,等待你的发现。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部