gpt4 book ai didi

c# - 如何在单独的库中声明相同的接口(interface)

转载 作者:太空宇宙 更新时间:2023-11-03 10:28:14 25 4
gpt4 key购买 nike

我需要在多个程序集中声明相同的接口(interface) - 但不引用公共(public)库。

我对接口(interface)有相同的定义,但是当我尝试从另一个应用程序创建它的实例时出现此错误:

Unable to cast object of type 'myFilter' to type 'DirectShow.IBaseFilter'

(myFilter 声明如下:public class myfilter : DirectSow.IBaseFilter...)

源对象使用RegAsm.exe注册

两个程序集都有声明:

[ComImport, System.Security.SuppressUnmanagedCodeSecurity,
Guid("56a86895-0ad4-11ce-b03a-0020af0ba770"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IBaseFilter : IMediaFilter
...

代码被复制,所以IMediaFilter和所有其他声明完全相同。

我尝试使用这个创建对象的实例:

 Type type = Type.GetTypeFromCLSID(new Guid("A3927399-E3AE-41E2-B094-0EA815CC9B9C"));
IBaseFilter filter = (IBaseFilter)Activator.CreateInstance(type);

如何跨程序集转换对象?

最佳答案

根据定义:你不能。两个彼此无关的独立接口(interface)永远不会是彼此"is"的关系,即使它们具有“相同”的命名和相同的成员。

专业的解决方案是在一个独立的程序集中分离接口(interface),然后根据需要引用该程序集的任意多个其他程序集。所有其他都被认为是黑客攻击(在 C#/.NET 中)。

要在这种特殊情况下应用所描述的解决方案,您需要 2 或 3 个程序集:

程序集 #1:(“定义”接口(interface))。这个“定义”是一个 COM 接口(interface)导入这个特殊情况:

 [ComImport, System.Security.SuppressUnmanagedCodeSecurity,
Guid("56a86895-0ad4-11ce-b03a-0020af0ba770"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IBaseFilter : IMediaFilter

大会#2: 引用 Assembly #1,并包含一个实现接口(interface)的类

大会#3: 引用 Assembly #1 和 #2,并且可以访问和使用/转换 Assembly #2 中的类。不要(重新)在此处导入接口(interface)。对于 .NET,这将是一个相同但完全“其他”的接口(interface),即使它具有完全相同的成员签名。

我认为 Assembly #1 和 #2 可以合并为一个。确保接口(interface)声明和类定义都是公开的。关键不是导入两次 COM 接口(interface),而是导入一次并引用它。

编辑:反射(reflect)到评论中:

不要将 COM 接口(interface)和类与 .NET 接口(interface)混淆。 (顺便说一下,评论中提到的是类 ID 而不是接口(interface) ID,这在 COM 中是两种不同的东西。)

通过互操作层高度支持访问 .NET 中的 COM 类和接口(interface)。互操作层为您完成所有转换和编码,您可以通过方便的 .NET 接口(interface)访问 COM 组件。然而,这个接口(interface)是在一个(互操作)组件中定义的,并且那些组件(对于众所周知的和经常使用的 COM 组件)是分布式的,或者是原始 COM 东西的一部分下载。因此,从字面上看,它们位于每台 需要的机器上。

还有一个概念差异,在 COM 中,客户端(引用组件)通过 一个 guid(这是类 ID)引用服务器(引用组件),然后请求多态实现一个界面也只有一个guid。因此,客户端可以通过只知道两个 guid 并执行 1-2 个 COM OS 调用来使用组件的特定接口(interface)。这是在互操作层中为您设置的黑盒。在 .NET 中,客户端和服务器之间的绑定(bind)要强得多。

如果想要定义这种类型的接口(interface),那么您必须做同样的事情:以某种方式在一个程序集中定义该接口(interface),然后将它分发到其他程序集所在的每台机器上正在使用该接口(interface)并引用该接口(interface)。

如果您不接受最佳实践的选项:

  • 您可以使用反射来实现类似的更宽松的绑定(bind),但在这种情况下,这被认为是黑客行为,而且似乎没有必要。准备好您的方法名称和类名称将是字符串,或者至少不正确输入它们不会导致编译错误,但会导致运行时错误。

  • 您还可以在 .NET 中定义和实现 COM 组件,但我认为这不是目标。 COM 是一种遗留(而且很酷)的技术,在当时非常进步(并且没有被理解/批评),但这是超过四分之一个世纪以前(当它被引入时)

关于c# - 如何在单独的库中声明相同的接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31051109/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com