gpt4 book ai didi

c# - 向 COM 公开 .NET 事件?

转载 作者:IT王子 更新时间:2023-10-29 04:27:48 25 4
gpt4 key购买 nike

我一直在尝试向 VBA 客户端公开和触发事件。到目前为止,在 VBA 客户端,事件已公开,我看到方法事件处理方法已添加到我的模块类中,但 VBA 事件处理方法未触发。由于某种原因,调试时事件为空。同步修改我的代码也无济于事。

作为记录,我已经检查了其他 SO 问题,但它们没有帮助。

任何好的答案将不胜感激。

[ComVisible(true)]
[Guid("56C41646-10CB-4188-979D-23F70E0FFDF5")]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IWebEvents))]
[ProgId("MyAssembly.MyClass")]
public class MyClass : ServicedComponent, IMyClass
{
public string _address { get; private set; }
public string _filename { get; private set; }

[DispId(4)]
public void DownloadFileAsync(string address, string filename)
{
_address = address;
_filename = filename;
System.Net.WebClient wc = new System.Net.WebClient();
Task.Factory.StartNew(() => wc.DownloadFile(_address, _filename))
.ContinueWith((t) =>
{
if (null != this.OnDownloadCompleted)
OnDownloadCompleted();
});
}
public event OnDownloadCompletedEventHandler OnDownloadCompleted;
}

[ComVisible(false)]
public delegate void OnDownloadCompletedEventHandler();

[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IWebEvents
{
[DispId(1)]
void OnDownloadCompleted();
}

这对你们所有的赏金猎人来说都是一场好戏,200 声望点数

最佳答案

.NET 代码中的关键概念是将事件定义为单独接口(interface)上的方法,并通过 [ComSourceInterfacesAttribute] 将其连接到类。在示例中,这是通过此代码完成的 [ComSourceInterfaces(typeof(IEvents))] 其中 IEvents 接口(interface)定义了应该在 COM 客户端上处理的事件。

事件命名注意事项:
c#类中定义的事件名和接口(interface)上定义的接口(interface)方法名必须相同。在此示例中,IEvents::OnDownloadCompleted 对应于 DemoEvents::OnDownloadCompleted

然后定义了第二个接口(interface),代表类本身的公共(public) API,这里称为 IDemoEvents。在此接口(interface)上定义了在 COM 客户端上调用的方法。

C# code (builds to COMVisibleEvents.dll)

using System;
using System.EnterpriseServices;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

namespace COMVisibleEvents
{
[ComVisible(true)]
[Guid("8403C952-E751-4DE1-BD91-F35DEE19206E")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IEvents
{
[DispId(1)]
void OnDownloadCompleted();
}

[ComVisible(true)]
[Guid("2BF7DA6B-DDB3-42A5-BD65-92EE93ABB473")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IDemoEvents
{
[DispId(1)]
Task DownloadFileAsync(string address, string filename);
}

[ComVisible(true)]
[Guid("56C41646-10CB-4188-979D-23F70E0FFDF5")]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IEvents))]
[ProgId("COMVisibleEvents.DemoEvents")]
public class DemoEvents
: ServicedComponent, IDemoEvents
{
public delegate void OnDownloadCompletedDelegate();
private event OnDownloadCompletedDelegate OnDownloadCompleted;
public string _address { get; private set; }
public string _filename { get; private set; }
private readonly string _downloadToDirectory =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

public async Task DownloadFileAsync(string address, string filename)
{
try
{
using (WebClient webClient = new WebClient())
{
webClient.Credentials = new NetworkCredential(
"user", "psw", "domain");
string file = Path.Combine(_downloadToDirectory, filename);
await webClient.DownloadFileTaskAsync(new Uri(address), file)
.ContinueWith(t =>
{
// https://stackoverflow.com/q/872323/
var ev = OnDownloadCompleted;
if (ev != null)
{
ev();
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
catch (Exception ex)
{
// Log exception here ...
}
}
}
}

regasm

C:\Windows\Microsoft.NET\Framework\v4.0.30319>regasm C:\Temp\COMVisibleEvents\bin\Debug\COMVisibleEvents.dll /tlb: C:\Temp\COMVisibleEvents\bin\Debug\COMVisibleEvents.tlb

VBA client reference to *.tlb file

添加对由 regasm 生成的 *tlb 的引用。此 tlb 文件的名称是 COMVisibleEvents

enter image description here

此处使用 Excel 用户窗体作为 VBA 客户端。单击按钮后,将执行 DownloadFileAsync 方法,当此方法完成时,事件将在处理程序 m_eventSource_OnDownloadCompleted 中捕获。在本示例中,您可以从我的保管箱下载 C# 项目 COMVisibleEvents.dll 的源代码。

VBA client code (MS Excel 2007)

Option Explicit

Private WithEvents m_eventSource As DemoEvents

Private Sub DownloadFileAsyncButton_Click()
m_eventSource.DownloadFileAsync "https://www.dropbox.com/s/0q3dskxopelymac/COMVisibleEvents.zip?dl=0", "COMVisibleEvents.zip"
End Sub

Private Sub m_eventSource_OnDownloadCompleted()
MsgBox "Download completed..."
End Sub

Private Sub UserForm_Initialize()
Set m_eventSource = New COMVisibleEvents.DemoEvents
End Sub

Result

enter image description here

关于c# - 向 COM 公开 .NET 事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39511528/

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