六、接口转换
现在部署的任何COM 组件都可以在接口转换中使用。通常情况下,所需的调整是完全自动进行的。
// 声明一个COM类 FilgraphManager
[ComImport, Guid("E436EBB3-524F-11CE-9F53-0020AF0BA770")] class FilgraphManager { }
class MainClass
{ public static void Main() { FilgraphManager filg = new FilgraphManager(); } }
声明 COM 接口
using System.Runtime.InteropServices;
// 声明一个COM接口 IMediaControl [Guid("56A868B1-0AD4-11CE-B03A-0020AF0BA770"), InterfaceType(ComInterfaceType.InterfaceIsDual)] interface IMediaControl // 这里不能列出任何基接口 { void Run(); void Pause(); void Stop(); void GetState( [In] int msTimeout, [Out] out int pfs); void RenderFile( [In, MarshalAs(UnmanagedType.BStr)] string strFilename); void AddSourceFilter( [In, MarshalAs(UnmanagedType.BStr)] string strFilename, [Out, MarshalAs(UnmanagedType.Interface)] out object ppUnk); [return : MarshalAs(UnmanagedType.Interface)] object FilterCollection(); [return : MarshalAs(UnmanagedType.Interface)] object RegFilterCollection(); void StopWhenReady(); }
若要防止 HRESULT 翻译为 COMException,请在 C# 声明中将 PreserveSig(true) 属性附加到方法。 下面是一个使用C# 映射媒体播放机COM 对象的程序。
using System;
using System.Runtime.InteropServices; namespace QuartzTypeLib { //声明一个COM接口 IMediaControl,此接口来源于媒体播放机COM类 [Guid("56A868B1-0AD4-11CE-B03A-0020AF0BA770"), InterfaceType(ComInterfaceType.InterfaceIsDual)] interface IMediaControl { //列出接口成员 void Run(); void Pause(); void Stop(); void GetState( [In] int msTimeout, [Out] out int pfs); void RenderFile( [In, MarshalAs(UnmanagedType.BStr)] string strFilename); void AddSourceFilter( [In, MarshalAs(UnmanagedType.BStr)] string strFilename, [Out, MarshalAs(UnmanagedType.Interface)] out object ppUnk); [return: MarshalAs(UnmanagedType.Interface)] object FilterCollection(); [return: MarshalAs(UnmanagedType.Interface)] object RegFilterCollection(); void StopWhenReady(); } //声明一个COM类: [ComImport, Guid("E436EBB3-524F-11CE-9F53-0020AF0BA770")] class FilgraphManager //此类不能再继承其它基类或接口 { //这里不能有任何代码 ,系统自动增加一个缺省的构造函数 } } class MainClass { public static void Main(string[] args) { //命令行参数: if (args.Length != 1) { DisplayUsage(); return; } String filename = args[0]; if (filename.Equals("/?")) { DisplayUsage(); return; } // 声明FilgraphManager的实类对象: QuartzTypeLib.FilgraphManager graphManager = new QuartzTypeLib.FilgraphManager(); //声明IMediaControl的实类对象:: QuartzTypeLib.IMediaControl mc = (QuartzTypeLib.IMediaControl)graphManager; // 调用COM的方法: mc.RenderFile(filename); //运行文件. mc.Run(); //暂借停. Console.WriteLine("Press Enter to continue."); Console.ReadLine(); } private static void DisplayUsage() { // 显示 Console.WriteLine("媒体播放机: 播放 AVI 文件."); Console.WriteLine("使用方法: VIDEOPLAYER.EXE 文件名"); } }
interop2 %windir%\clock.avi
namespace System.Runtime.InteropServices
{ [AttributeUsage(AttributeTargets.Method)] public class DllImportAttribute: System.Attribute { public DllImportAttribute(string dllName) {} public CallingConvention CallingConvention; public CharSet CharSet; public string EntryPoint; public bool ExactSpelling; public bool PreserveSig; public bool SetLastError; public string Value { get {} } } }
说明:
using System;
using System.Runtime.InteropServices; class MainApp { //通过DllImport引用user32.dll类。MessageBox来自于user32.dll类 [DllImport("user32.dll", EntryPoint="MessageBox")] public static extern int MessageBox(int hWnd, String strMessage, String strCaption, uint uiType); public static void Main() { MessageBox( 0, "您好,这是 PInvoke!", ".NET", 0 ); } }
面向对象的编程语言几乎都用到了抽象类这一概念,抽象类为实现抽象事物提供了更大的灵活性。C#也不例外, C#通过覆盖虚接口的技术深化了抽象类的应用。要了解这方面的知识,请看下一节—覆盖虚接口。 |
|