Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否通过互操作将VB6对象传递给.NET对象?_C#_.net_Vb6_Com Interop - Fatal编程技术网

C# 是否通过互操作将VB6对象传递给.NET对象?

C# 是否通过互操作将VB6对象传递给.NET对象?,c#,.net,vb6,com-interop,C#,.net,Vb6,Com Interop,我有一个VB6应用程序,通过互操作显示.NET DLL表单 我希望.NET DLL中的事件导致VB6应用程序中的窗体显示 我的想法是让VB6应用程序将对表单的引用传递到.NETDLL。例如: [VB6] Dim objNetDllObject As New NetDllObject objNetDllObject.PassVb6Form(MyForm) objNetDllObject.ShowForm [C#] object Vb6Form; private void PassVb6Form

我有一个VB6应用程序,通过互操作显示.NET DLL表单

我希望.NET DLL中的事件导致VB6应用程序中的窗体显示

我的想法是让VB6应用程序将对表单的引用传递到.NETDLL。例如:

[VB6]
Dim objNetDllObject As New NetDllObject
objNetDllObject.PassVb6Form(MyForm)
objNetDllObject.ShowForm

[C#]
object Vb6Form; 
private void PassVb6Form(object form) { Vb6Form = form; }
private void button1_Click(object sender, EventArgs e) { Vb6Form.Show(); }
这样行吗


我在其他地方读到过,跨越“进程边界”发送对象可能会导致问题。这是否正确?

一种方法是在.NET中定义COM接口:

<System.Runtime.InteropServices.GuidAttribute("0896D946-8A8B-4E7D-9D0D-BB29A52B5D08"), _
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface IEventHandler
    Sub OnEvent(ByRef sender As Object, ByRef e As Object)
End Interface
然后在.NET中有一个带有IEventHandler静态集合的注册器:

<ComClass(ComRegistrar.ClassId, ComRegistrar.InterfaceId, ComRegistrar.EventsId>
Public Class ComRegistrar

   Private Shared ReadOnly _eventHandlers As New Dictionary(Of String, List(Of IEventHandler))


   ' This is called by .NET code to fire events to VB6
   Public Shared Sub FireEvent(ByVal eventName As String, ByVal sender As Object, ByVal e As Object)
        For Each eventHandler In _eventHandlers(eventName)
                eventHandler.OnEvent(sender, e)
        Next
   End Sub

   Public Sub RegisterHandler(ByVal eventName As String, ByVal handler As IEventHandler)
        Dim handlers as List(Of IEventHandler)
        If Not _eventHandlers.TryGetValue(eventName, handlers)
             handlers = New List(Of IEventHandler)
             _eventHandlers(eventName) = handlers
        End If
        handlers.Add(handler)
   End Sub

End Class

公共类通信注册器
私有共享只读事件处理程序作为新字典(字符串、列表(IEventHandler))
'这由.NET代码调用,以将事件激发到VB6
公共共享子FireEvent(ByVal eventName作为字符串,ByVal sender作为对象,ByVal e作为对象)
对于_eventHandlers(eventName)中的每个eventHandler
eventHandler.OneEvent(发送方,e)
下一个
端接头
公共子寄存器句柄(ByVal eventName作为字符串,ByVal句柄作为IEventHandler)
作为列表的Dim处理程序(IEventHandler)
如果不是_eventHandlers.TryGetValue(eventName,handlers)
处理程序=新列表(IEventHandler)
_eventHandlers(eventName)=处理程序
如果结束
添加(处理程序)
端接头
末级
您的.NET代码将调用FireEvent,如果VB6以前调用过RegisterHandler,您的VB6 IEvenHandler将被调用。

您还可以使用,这将使代码更简单(或者至少从VB6方面来说更自然)。您将获得如下代码:

C#图书馆:

以及VB6客户端:

选项显式
Private,事件f作为WindowsFormsControlLibrary1.MyForm
专用子命令1_Click()
Set f=New windowsforms控件库1.MyForm
呼叫f.Show
端接头
私人分公司f_MyEvent()
MsgBox“事件是从.NET引发的”
'打开另一个VB6窗体或执行任何需要的操作
端接头

如果您打算从VB6应用程序中使用大量的.NET UI,我强烈建议您使用。(它有助于生成类似于这些示例的代码,以及处理一些其他常见场景)。

这不是流程边界,而是同一流程。是的,这很痛苦,但它可以工作。我的方法不是更简单吗?我试图避免所有那些事件处理的东西。是的,更简单,但您需要使用后期绑定来进行回调。在这种情况下,后期绑定有什么风险?与通常的一样:)…方法不存在。你没有正确地调用它。签名更改…等等。签名将如何更改?
<ComClass(ComRegistrar.ClassId, ComRegistrar.InterfaceId, ComRegistrar.EventsId>
Public Class ComRegistrar

   Private Shared ReadOnly _eventHandlers As New Dictionary(Of String, List(Of IEventHandler))


   ' This is called by .NET code to fire events to VB6
   Public Shared Sub FireEvent(ByVal eventName As String, ByVal sender As Object, ByVal e As Object)
        For Each eventHandler In _eventHandlers(eventName)
                eventHandler.OnEvent(sender, e)
        Next
   End Sub

   Public Sub RegisterHandler(ByVal eventName As String, ByVal handler As IEventHandler)
        Dim handlers as List(Of IEventHandler)
        If Not _eventHandlers.TryGetValue(eventName, handlers)
             handlers = New List(Of IEventHandler)
             _eventHandlers(eventName) = handlers
        End If
        handlers.Add(handler)
   End Sub

End Class
namespace WindowsFormsControlLibrary1
{
    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;

    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IMyFormEvents
    {
        [DispId(1)]
        void MyEvent();
    }

    public delegate void MyEventEventHandler();

    [ComSourceInterfaces(typeof(IMyFormEvents))]
    public partial class MyForm : Form
    {
        public event MyEventEventHandler MyEvent;

        public MyForm()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (this.MyEvent != null)
            {
                this.MyEvent();
            }
        }
    }
}