基于COM的.net插件框架

时间:2012-07-04 10:25:33

标签: c# .net com com-interop

我有一个ASP.NET MVC3网站,必须使用COM插件。为了做到这一点,我需要以某种方式定义一个接口。据我所知(我不是COM专家),这可以在.NET中完成,并使用tlbexp.exe或idl-> midl-> tlbimp导出。

我已经走了第一条路(用tlbexp)。我也尝试过IDL,但无济于事(由于某种原因,可以将实现COM对象强制转换回.NET中的tlbimp'ed接口。)

如果我的界面上没有事件,这种情况会很简单:

[ComVisible(true)]
[Guid("EFCFB783-0225-4D45-94CB-9A26B7CC19AF")]
public delegate void ItemStatusChanged(string itemGuid, string itemStatus);

[ComVisible(true)]
[Guid("35202AE5-392D-4015-993D-29966DA5DE31")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface ICOMOutputPlugin
{
    void Method1(string arg);
    void Method2(string arg);
    event ItemStatusChanged ItemStatusChanged;
}

[ComVisible(true)]
[Guid("93862C43-503C-4C96-9BAE-944F1087AB77")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ICOMOutputPluginEvents
{
    void ItemStatusChanged(string itemGuid, string itemStatus);
}

我使用tlbexp.exe将其导出到tlb并使用regtlibv12注册.tlb。 插件开发人员将仅使用此类型库来导入接口。

现在我有一个C ++项目,它将是一个插件,我在VS2010中添加了新的简单ATL对象并将IDL更改为:

importlib("stdole2.tlb");
importlib("MyExp.tlb");

[
    uuid(E09BC67A-4192-4CA3-8FD0-5CBFC69B43AC)      
]
coclass DumpToFileOutputPlugin
{
    [default] interface ICOMOutputPlugin;
    [default, source] dispinterface ICOMOutputPluginEvents;
};

我的第一个问题是,由于某种原因,我无法通过类向导将连接点添加到“正常方式”。当我将它指向MyExp.tlb时,它根本不显示任何源接口。所以我手动完成了(使用了另一个.tlb并重命名了所有内容)。

所以现在我有了这两种方法的COM对象:

STDMETHOD(add_ItemStatusChanged)(_ItemStatusChanged* value);
STDMETHOD(remove_ItemStatusChanged)(_ItemStatusChanged* value);

在.NET端,插件管理器实例化这样的插件:

Type type = Type.GetTypeFromProgID(progID);
comObject = Activator.CreateInstance(type) as ICOMOutputPlugin;
comObject.ItemStatusChanged += (guid, status) => ItemStatusChanged(guid, status);

最后一行奇迹般地在我的COM对象上调用add_ItemStatusChanged方法。

在这里,我被困住了,这个方法我该怎么办?我目前的实施是:

HRESULT CDumpToFileOutputPlugin::add_ItemStatusChanged(_ItemStatusChanged* value)
{
        DWORD cookie;
        HRESULT ret = Advise(value, &cookie);
        _com_error err(ret);
        LPCTSTR errMsg = err.ErrorMessage();
        return ret;
}

ret = CONNECT_E_CANNOTCONNECT(0x80040202),errMsg说“IDispatch错误#2”。 显然Advise期望传递的COM对象实现委托传递对象的连接点接口ICOMOutputPluginEvents ...我该怎么办?

我是否在.NET端订阅了错误的事件或添加处理程序?

任何帮助如何解决这个问题将不胜感激。

1 个答案:

答案 0 :(得分:-1)

不要在ASP.Net的COM插件中使用“事件”,只需要调用方法即可。即一个名为OnEventName的方法,而不是一个事件。

COM事件不是处理Web表单回发的正确方法。