C# 如何在单独的库中声明相同的接口
我需要在多个程序集中声明相同的接口,但不能引用公共库 我对接口有相同的定义,但当我尝试从另一个应用程序创建接口实例时,出现了以下错误: 无法将“myFilter”类型的对象强制转换为 “DirectShow.IBaseFilter” (myFilter的声明类似于:C# 如何在单独的库中声明相同的接口,c#,interface,com,directshow,C#,Interface,Com,Directshow,我需要在多个程序集中声明相同的接口,但不能引用公共库 我对接口有相同的定义,但当我尝试从另一个应用程序创建接口实例时,出现了以下错误: 无法将“myFilter”类型的对象强制转换为 “DirectShow.IBaseFilter” (myFilter的声明类似于:公共类myFilter:DirectSow.IBaseFilter…) 使用RegAsm.exe注册源对象 两个程序集都有以下声明: [ComImport, System.Security.SuppressUnmanagedCodeS
公共类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);
如何跨程序集强制转换对象?根据定义:不能。两个彼此无关的独立接口永远不会是彼此之间的关系,即使它们具有“相同”的命名和相同的成员 专业解决方案是在独立程序集中分离接口,然后根据需要引用此程序集。所有其他的都被认为是黑客行为(在C#/.NET中) 要在此特定情况下应用所述解决方案,您需要2或3个组件: 汇编#1:(它“定义”接口)。此“定义”是一个COM接口,在这种特殊情况下:
[ComImport, System.Security.SuppressUnmanagedCodeSecurity,
Guid("56a86895-0ad4-11ce-b03a-0020af0ba770"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IBaseFilter : IMediaFilter
装配#2:
引用程序集#1,并包含一个实现接口的类
装配#3:
引用程序集#1和#2,可以访问和使用/强制转换程序集#2中的类。不要在此处(重新)导入接口。对于.NET来说,这将是一个完全相同但完全“其他”的接口,即使它具有完全相同的成员签名
我认为大会1和2可以合并为一个。确保接口声明和类定义都是公共的。键不是两次导入COM接口,而是一次导入并引用它
编辑:反映到评论:
不要将COM接口和类与.NET接口混淆。(顺便说一句,注释提到的是类id而不是接口id,这在COM中是两个不同的东西。)
通过互操作层高度支持访问.NET中的COM类和接口。互操作层为您完成所有转换和编组,您可以通过方便的.NET接口访问COM组件。然而,这个接口是在(互操作)组件中定义的,这些组件(对于众所周知的、经常使用的COM组件)是分布式的,或者是原始COM组件下载的一部分。因此,从字面上说,他们是在每台机器上,他们需要
还有一个概念上的差异,即在COM中,客户端(引用组件)仅通过guid(这是类id)引用服务器(引用组件),然后请求接口的多态实现,也仅通过guid。因此,客户机可以通过只知道两个GUI并执行1-2 COM OS调用来使用组件的特定接口。这是互操作层中的黑框。在.NET中,客户端和服务器之间的绑定要强大得多
如果要定义此类接口,则必须执行相同的操作:以某种方式在一个程序集中定义接口,然后将其分发给其他程序集使用接口并引用此接口的每台计算机
如果您不接受最佳实践,请选择:
- 您可以使用反射来实现类似的松散绑定,但在本例中,这被认为是黑客行为,似乎没有必要。请准备好,方法名和类名将是字符串,或者至少键入不正确不会导致编译错误,但会导致运行时错误
- 您也可以在.NET中定义和实现COM组件,但我认为这不是目标。COM是一种传统的(很酷的)技术,在当时是非常进步的(不被理解/批评),但这是四分之一个多世纪前(当它被引入时)
- (这是问题作者的答案)
在DLL中:
使组件
COM可见=选中
using System;
using System.Runtime.InteropServices;
namespace ComExport
{
[ComImport]
[Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[TypeIdentifier()]
public interface ComClass1Interface
{
string DoCall();
}
[Guid("0D53A3E8-E51A-49C7-944E-E72A2064F938")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class ComClass1 : ComClass1Interface
{
public string DoCall()
{
return "internal function called";
}
public override string ToString()
{
return "comclass1.tostring";
}
}
}
然后在EXE中
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ComExportTester
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += (o1, e) => Close();
Type t;
object o;
ComExport.ComClass1Interface i1;
string s = "";
try
{
t = Type.GetTypeFromCLSID(new Guid("0D53A3E8-E51A-49C7-944E-E72A2064F938"));
s += "Type found \t: " + (t == null ? "no" : "yes") + "\n";
o = t == null ? null : Activator.CreateInstance(t);
s += "object created \t: " + (o == null ? "no" : o.ToString()) + "\n";
i1 = o as ComExport.ComClass1Interface;
s += "interface cast \t: " + (i1 == null ? "no" : "yes") + "\n";
if (i1 != null)
s += i1.DoCall() + "\n";
}
catch (Exception x)
{
s += x.Message + "\n";
}
MessageBox.Show(s);
}
}
}
namespace ComExport
{
[ComImport]
[Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[TypeIdentifier()]
public interface ComClass1Interface
{
string DoCall();
}
}
在这两方面:
设置x86或x64(在“任意CPU”模式下编译和运行会引发“未注册”异常!)为什么不引用公共程序集?为什么不将接口拉入其自己的程序集,并让它们都引用该程序集?“我需要在多个程序集中声明相同的接口,但不引用公共库”. 这是不可能的。除非它们都引用一个定义,否则接口就不一样了。C#不支持duck类型。很难猜到为什么程序员坚持这样做。从技术上讲,COM接口从.NET 4.0开始仅通过其[Guid]支持类型等效。用于实现互操作程序集的“嵌入互操作类型”属性的功能。Google“.net类型等效”了解更多信息。这是一个使用COM的DirectShow项目。我无法与其他供应商共享通用代码,但我制作的对象已成功加载到GraphiEdit中,并可用于我机器上的所有其他视频处理系统。如果我使用类id“70E102B0-5556-11CE-97C0-00AA0055595A”,我会得到一个内置的视频渲染器,然而,它以某种方式成功地公开了IBaseFilter接口。由于这个特殊的例子是DirectShow,我的程序正在访问系统级已知接口,因此通用全局级接口被隐藏在操作系统中。我的库中的一个类实现了该接口,但由于某些原因,我无法从单独的程序集访问它。我的两个程序集都可以访问实现该接口的系统上的所有其他程序集,系统上的所有程序集都可以访问我的类-只是我的两个类不能相互访问。@g.pickardou,实际上,你可以,但它是一个。请