• new 一个接口?


    如果有人问你,C# 中可以new 一个接口吗?,你会怎么回答?

    假设ITestInterface 是一个接口,那么这样的代码是否有问题?

    ITestInterface testInterface = new ITestInterface();

    很多书上都会说,当然有问题,接口不能用new ,然后你就认为上面这句语句肯定通不过编译器的编译了。

    可是凡事无绝对,C# 竟然允许你这么写,当然你需要加点”料”才行。

    VS2005 中新建控制台程序CA2005.添加 Microsoft.Office.Interop.Excel 引用

    image

    image

    Program 的Main函数只有一句话:

    image

    注意,可以通过编译,看下Application的定义:

    image

    很明显Application 是个interface,

    这里我要扯一下,经常看到有人说string 是类还是结构什么的,看下string 的定义:

    image

     String 是用class 来修饰的,所以string 100% 是类。

    还是扯回来吧,Application 是个接口,但是我们却可以用new  .为什么

    先看下反编译后的代码吧:

    image

     

    可以看到虽然我们写的是new Application,但是编译器为我们生成的却是new ApplicationClass();

    难道Application 有什么特别的地方?

    仔细的同学一眼就看出了Application是被这两个特性修饰的:

    [CoClass(typeof(ApplicationClass))]

    [Guid("000208D5-0000-0000-C000-000000000046")]

    关于CoClass的解释可以看msdn

    image

     

    有些人不喜欢看msdn,而喜欢看博客的一个原因就是msdn太不直白了。

    我个人的理解是CoClass 就好像concrete Class(具体类)

    这个特性指示编译器在编译Application的时候,使用ApplicationClass 来实现。

    回到上面的最初的问题上:

    如何让这段代码通过编译:

    ITestInterface testInterface = new ITestInterface();

    通过上面的分析,我们很容易将这个特性来修饰我们的自己的接口:

    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();

            }

        }

    }

    编译,结果如下:

    image

    接口被标记了CoClassAttribute,而不是ComImportAttribute.

    image

    原来想要new 一个接口使用的是编译器对COM的优化和支持。

    很明显上面的Application是一个COM对象,所以可以new Application

    ITestApplication中添加ComImportAttribute 特性:

    clip_image002

    再次运行,结果如下:

    image

    查看下反编译的代码:

    image

    之所以我对VS2005 用红色字体,是因为如果你用VS2010 创建的程序,那么你会看到不一样的反编译结果:

    public static void Main()

    {

          Application application1 = (Application) Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("00024500-0000-0000-C000-000000000046")));

          ITestInterface interface1 = new TestClass();

          interface1.DoSomething();

          Console.ReadLine();

    }

    这里的Type.GetTypeFromCLSID 中的guidApplicationClassGuid,也就是CoClassTypeGuid

    [ComSourceInterfaces("Microsoft.Office.Interop.Excel.AppEvents")]

        [Guid("00024500-0000-0000-C000-000000000046")]

        [TypeLibType(2)]

        [ClassInterface(0)]

        public class ApplicationClass : _Application, Application, AppEvents_Event

    {

    }

    这点一定要注意。

    楼下有些同学说这有什么意义,下面是我的项目实例,也是这个问题才让我研究了这个问题:

    在项目中使用了一种C3读卡器,这种读卡器提供了读卡接口(C3ReadCard),但是开发环境是2005,所以不能够C3ReadCard c3=new C3ReadCard();

    这点很奇怪,Excel的可以new,但是C3ReadCard却不可以new,但是通过反射去调用实现类就可以使用C3ReadCard的接口。

    这个问题的意义在于你明白编译器如何去处理new一个接口所生成的代码,也许还有其他的用处,等待你的发现。

  • 相关阅读:
    'live-server' 不是内部或外部命令,也不是可运行的程序 或批处理文件。(解决)
    Node.js安装及环境配置之Windows篇
    开发模式
    IOS13越狱后虚拟定位插件的推荐,relocate
    python,向列表中追加字典,被最后的值覆盖的问题解决办法
    博客园cnblog使用百度统计等站长统计的方法
    IOS解锁哔哩哔哩大会员免费版越狱插件的cydia源
    filza无法安装deb(filza command not found)的解决办法
    Mac 中dock栏图标中文乱码英文正常的解决办法
    关于NVIDIA显卡控制面板中“调整桌面颜色设置”在重启后设置失效的处理方法
  • 原文地址:https://www.cnblogs.com/LoveJenny/p/2288313.html
Copyright © 2020-2023  润新知