2

私が持っているのは、プライベート機能とパブリック機能の両方を持つメイン アプリケーションのフォームの束です。各フォームが作成およびロードされたときにアクセスし、更新、コントロールの追加などのためにフォームへの参照を保持するプラグイン アーキテクチャを配置しています。

私たちがやろうとしているのは、このプラグイン アーキテクチャを実装することですが、一部のプラグインはフォームのプライベート関数を呼び出す必要がある場合があります。Type.InvokeMember で試した例を次に示します。

public partial class Form1 : Form
{
    Form1()
    {
        InitializeComponent();
    }

    private void SayHello()
    {
        MessageBox.Show("Hello World!");
    }
}

別のDLLで...

public class PluginClass
{
    Form1 myReferencedForm1;

    PluginClass()
    {
        //Constructor code here...

        //Also sets the reference to existing Form1 instance
    }

    private CallMember()
    {
        Type t = typeof(Form1); //I guess I can also call 'myReferencedForm1.GetType();' here as well
        t.InvokeMember("SayHello",
                       System.Reflection.BindingFlags.InvokeMethod |
                       System.Reflection.BindingFlags.NonPublic |
                       System.Reflection.BindingFlags.Public,
                       null, myReferencedForm1, new object[] { });
    }
}

私は試してみ"SayHello"ましたが"SayHello()"、どちらも「MissingMethodException」エラーを返します:

Method 'Form1.SayHello()' not found.

バインダーを作成して使用する必要がありますか? もしそうなら、どうすればいいですか?System.Windows.Forms.Message でこれを簡単に行うことはできますか? もしそうなら、どのように?

4

5 に答える 5

2

それを試さないでください。

インターフェイスを作成します: IPluginHostwith DoMethod(string Name)member. フォームごとにそのインターフェイスを実装しますpartial class。宣言を使用して他のファイルに抽出することもできます。

メソッド impl では、単純な switch case を実行して、適切なメソッドをキックします。スクリプトを使用して生成します。

public interface IPluginHost
{
    void DoMethod(string MethodName);
}

public partial MyForm:Form, IPluginHost
{
    #region IPluginHost implementation
    public void DoMethod(string MethodName)
    {
         switch (MethodName)
             case "SayHello":
                 SayHello();
                 break;
             ...
    }
    #endregion
}

アーキテクチャを担当している場合は、最初から IT をハックしないでください。

于 2010-12-01T18:15:05.510 に答える
1

フラグのリストに含まBindingFlags.Instanceれていないため、チェックするインスタンスまたは静的メソッドがありません!

個人的には、通常、呼び出してから、メソッドの発見を呼び出しから分離しますGetMethodMethodInfo.Invokeその方がデバッグしやすいと思いますが、YMMV.

完全なサンプル:

using System;
using System.Reflection;

class OtherClass
{
    private void Foo()
    {
        Console.WriteLine("OtherClass.Foo");
    }
}

class Test
{
    static void Main()
    {
        OtherClass target = new OtherClass();
        typeof(OtherClass).InvokeMember("Foo",
            BindingFlags.InvokeMethod | BindingFlags.Instance |
            BindingFlags.Public | BindingFlags.NonPublic,
            null, target, new object[0]);
    }
}

または、「呼び出しからの個別のフェッチ」を使用します。

using System;
using System.Reflection;

class OtherClass
{
    private void Foo()
    {
        Console.WriteLine("OtherClass.Foo");
    }
}

class Test
{
    static void Main()
    {
        OtherClass target = new OtherClass();
        MethodInfo method = typeof(OtherClass).GetMethod("Foo",
            BindingFlags.InvokeMethod | BindingFlags.Instance |
            BindingFlags.Public | BindingFlags.NonPublic);

        // Could now check for method being null etc
        method.Invoke(target, null);
    }
}
于 2010-12-01T18:12:49.677 に答える
0

BindingFlags を次のように変更します

private CallMember()
{
    Type t = typeof(Form1); //I guess I can also call 'myReferencedForm1.GetType();
    t.InvokeMember("SayHello",
                   System.Reflection.BindingFlags.InvokeMethod |
                   System.Reflection.BindingFlags.Instance |
                   System.Reflection.BindingFlags.NonPublic,
                   null, myReferencedForm1, new object[] { });
}

これでうまくいくはずです。

于 2010-12-01T18:18:58.077 に答える
0

BindingFlags.Instanceフラグのリストに追加するのを忘れました:

t.InvokeMember("SayHello", 
               BindingFlags.Intance |
                   BindingFlags.InvokeMethod |
                   BindingFlags.NonPublic,
               null, 
               myReferencedForm1,
               new object[] { });

しかし、正直なところ、私はメソッドを取得してから、返された MethodInfo オブジェクトを使用してメソッドを呼び出すことを好みます。

if(myReferencedForm1 != null)
{
    var type = typeof(Form1);
    var method = type.GetMethod("SayHello", BindingFlags.Instance
        | BindingFlags.NonPublic);

    method.Invoke(myReferencedForm1);
}
于 2010-12-01T18:12:08.947 に答える
0

invokeAttrパラメータは

BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic
于 2010-12-01T18:14:26.563 に答える