0

C# DLL から VB アプリにハンドラを追加する方法を知っている人がいます。VB プロジェクトで AddHandler を使用しようとすると、Visual Studio から次のように返されます。

Error   BC30676 'DebugMessageEvent' is not an event of 'Debugger'...

Debugger.Instance.DebugMessageEvent は、Debugger と呼ばれる独自のクラスを持つ DLLNAMESPACE と呼ばれる DLL の一部であり、他のメソッドに関する情報を送信し、DLLNAMESPACE と呼ばれる DLL 内の他のクラスからプロセスします。

ここに画像の説明を入力

VB Proj (DLLNAMESPACE と呼ばれる DLL から自動変換) から 'DebugMessageEvent' 定義に移動すると、次のコードが得られます。

Public Class Debugger
    Public DebugMessageEvent As EventHandler(Of DebugMessageArgs)

    Public Shared ReadOnly Property Instance As Debugger

    Public Class DebugMessageArgs
        Inherits EventArgs

        Public Sub New()

        Public Property Message As Object
    End Class
End Class

VB プロジェクト (動かない)

Imports DLLNAMESPACE
Public Class myclass
    ...
    Private Sub backup(...)
        AddHandler Debugger.Instance.DebugMessageEvent, AddressOf console_DebugMessageEvent
        ...
    End Sub
    ...
    Private Sub console_DebugMessageEvent(sender As Object, e As Debugger.DebugMessageArgs)
        Console.WriteLine(e.Message)
    End Sub
    ...
End Class

別の C# プロジェクト (作品)

using DLLNAMESPACE;
public partial class myclass : Form
{
    ...
    private void backup()
    {
        Debugger.Instance.DebugMessageEvent += console_DebugMessageEvent;
        ...
    }
    ...

    void console_DebugMessageEvent(object sender, Debugger.DebugMessageArgs e)
    {
        Console.WriteLine(e.Message);
    }
    ...
}

ここに画像の説明を入力

DLL C# コード

using System;
namespace DLLNAMESPACE
{
    public sealed class Debugger
    {
        private static readonly Lazy<Debugger> instance = new Lazy<Debugger>(() => new Debugger());

        private Debugger()
        {

        }

        public static Debugger Instance
        {
            get { return instance.Value; }
        }

        public EventHandler<DebugMessageArgs> DebugMessageEvent;

        public class DebugMessageArgs : EventArgs
        {
            public object Message { get; set; }
        }

        private void RaiseDebugMessageEvent(object message)
        {
            DebugMessageEvent?.Invoke(this, new DebugMessageArgs
            {
                Message = message
            });
        }

        internal void DebugMessage(object data)
        {
            RaiseDebugMessageEvent(data);
        }
    }
}

残りのすべての DLL 関数は期待どおりに機能します。アドバイスをお願いします。DLL のコードは変更したくありません。VB.NET コードだけを変更したいのです。

いくつかの失敗したテスト

Visual Studio の検証に合格しますが、DLLNAMESPACE に関連付けられている他のバックグラウンド プロセスが閉じます。

新しい EventHandler

Imports DLLNAMESPACE
Public Class myclass
    ...
    Private Sub backup(...)
        Debugger.Instance.DebugMessageEvent = New EventHandler(Of Debugger.DebugMessageArgs)(AddressOf console_DebugMessageEvent)
        ...
    End Sub
    ...
    Private Sub console_DebugMessageEvent(sender As Object, e As Debugger.DebugMessageArgs)
        Console.WriteLine("Consola RoboSharp: " & e.Message)
    End Sub
    ...
End Class

ダイレクトキャスト

Imports DLLNAMESPACE
Public Class myclass
    ...
    Private Sub backup(...)
        Debugger.Instance.DebugMessageEvent = DirectCast(System.Delegate.Combine(Debugger.Instance.DebugMessageEvent, DirectCast(AddressOf console_DebugMessageEvent, EventHandler(Of Debugger.DebugMessageArgs))), EventHandler(Of Debugger.DebugMessageArgs))
        ...
    End Sub
    ...
    Private Sub console_DebugMessageEvent(sender As Object, e As Debugger.DebugMessageArgs)
        Console.WriteLine("Consola RoboSharp: " & e.Message)
    End Sub
    ...
End Class

誰かが私の問題を再現する時間があれば、nuget の robosharp を使用してみて、それを vb.net プロジェクトに追加してください。

4

2 に答える 2

1

「DebugMessageEvent」はイベントではないため、「AddHandler」でそのように扱うことはできません。これはデリゲート型のフィールドであるため、代わりに次を使用できます。

Debugger.Instance.DebugMessageEvent = DirectCast(System.Delegate.Combine(Debugger.Instance.DebugMessageEvent, DebugMessage), EventHandler(Of DebugMessageArgs))
于 2016-11-27T17:55:21.210 に答える
0

解決策によって DLL を使用している他のアプリケーションがクラッシュする場合Delegate.Combine()は、C# DLL を作成してハンドラーを追加するのが最善の解決策だと思います。

例えば:

using System;

namespace DebuggerHelperDLL
{
    public static class DebuggerHelper
    {
        public static void AddHandler(EventHandler<Debugger.DebugMessageArgs> eventHandler)
        {
            Debugger.Instance.DebugMessageEvent += eventHandler;
        }
    }
}

次に、VB.NET プロジェクトで次のようにします。

DebuggerHelper.AddHandler(AddressOf console_DebugMessageEvent)

+=演算子を使用してコンパイルされた C# DLL が IL に逆コンパイルされたときにこれが生成されるため、機能しないのは奇妙に思えます。

.method public hidebysig static 
    void AddHandler (
            class [mscorlib]System.EventHandler`1<class DLLNAMESPACE.Debugger/DebugMessageArgs> eventHandler
    ) cil managed 
{
    // Method begins at RVA 0x211c
    // Code size 29 (0x1d)
    .maxstack 8

    IL_0000: nop
    IL_0001: call class DLLNAMESPACE.Debugger DLLNAMESPACE.Debugger::get_Instance()
    IL_0006: dup
    IL_0007: ldfld class [mscorlib]System.EventHandler`1<class DLLNAMESPACE.Debugger/DebugMessageArgs> DLLNAMESPACE.Debugger::DebugMessageEvent
    IL_000c: ldarg.0
    IL_000d: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
    IL_0012: castclass class [mscorlib]System.EventHandler`1<class DLLNAMESPACE.Debugger/DebugMessageArgs>
    IL_0017: stfld class [mscorlib]System.EventHandler`1<class DLLNAMESPACE.Debugger/DebugMessageArgs> DLLNAMESPACE.Debugger::DebugMessageEvent
    IL_001c: ret
} // end of method DebuggerHelper::AddHandler

offsetIL_000dでわかるように、次のように呼び出しますSystem.Delegate::Combine()

call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
于 2016-11-27T23:07:06.357 に答える