パラメータを持つ代理人...をパラメータとして

私は、WinFormsアプリケーション内のスレッドからGUIの複数行TextBoxにテキストを追加するために使用されるデリゲートでこのメソッドを持っています:

private delegate void TextAppendDelegate(TextBox txt, string text);
public void TextAppend(TextBox txt, string text)
{
  if(txt.InvokeRequired)
    txt.Invoke(new TextAppendDelegate(TextAppend), new object[] {txt, text });
  else
  {
    if(txt.Lines.Length == 1000)
    {
      txt.SelectionStart = 0;
      txt.SelectionLength = txt.Text.IndexOf("\n", 0) + 1;
      txt.SelectedText = "";
    }
    txt.AppendText(text + "\n");
    txt.ScrollToCaret();
  }
}

それは素晴らしい、私はちょうど任意のスレッドからTextAppend(myTextBox1、 "こんにちは!")を呼び出すと、GUIが更新されます。今、実際のTextBoxへの参照を何も送らずに、別のプロジェクトのユーティリティメソッドの1つにTextAppendを呼び出すデリゲートを渡す方法はありますか?

Utilities.myUtilityMethod(
    new delegate(string str){ TextAppend(myTextBox1, str) });

また、呼び出し先では、次のような定義があります。

public static void myUtilityMethod(delegate del)
{
    if(del != null) { del("Hi Worldo!"); }
}

この関数が呼び出されると、その文字列と呼び出し元が使用する定義済みのTextBoxを持つTextAppendメソッドが呼び出されます。これは可能ですか、私は狂っていますか?インターフェイスの使用やTextBoxとデリゲートの渡し方などの簡単なオプションがあることはわかっていますが、このソリューションはより洗練されているように見えますし、呼び出し先から情報を隠すためです。問題は、私がまだC#で​​初心者で、代議員をほとんど理解していないということです。実際の構文がうまくいくかどうか教えてください。

前もって感謝します!

5
要件の理解を深めるための質問がいくつかあります。あなたの myUtilityMethod が、単一の文字列をデリゲートに渡す必要があることを、あなたはどのように期待していますか?そして、あなたはそれが文字列を通過することをどのように期待していますか?
追加された 著者 Enigmativity,
TextAppendメソッド全体をユーティリティクラスに移動してから、呼び出し元からUtility.TextAppend(MyTextbox、 "foo")を実行することはできませんか?
追加された 著者 Dylan Smith,
@RRuiz TextAppendをUtilityクラスに移動すると、TextAppendがそれを作成するため、デリゲートを渡す必要はありません。テキストボックスへの参照と追加したい文字列を渡すだけです。私にはユーティリティメソッドの完全な使用のように聞こえます(私はTextBoxクラスの拡張メソッドにすることもあります)。
追加された 著者 Dylan Smith,
どのようなバージョンの.NET/C#?
追加された 著者 Platinum Azure,
@Platinum Azureバージョンは3.5です
追加された 著者 R. Ruiz.,
@Dylan SmithユーティリティをGUIに更新できるように、メソッドをユーティリティに移動したくないので、TextBoxへの参照とメソッドTextAppendへの代理を渡す必要があるためです。それは簡単な解決策ですが、私はもっとシールドされたものを持っていたいと思います
追加された 著者 R. Ruiz.,
@Enigmativityそれは良い質問であり、わかりません。たぶんユーティリティのパラメータは次のようなものでなければなりません:public static void myUtilityMethod(delegate(string)del)?????それは私が知らないもので、あなたの何人かが親切に説明してくれることを願っています
追加された 著者 R. Ruiz.,
@Dylan Smithありがとう、私はそれがより直接的な解決策であることは分かっていますが(おそらくは読みやすく保守的かもしれませんが)、プログラムのいくつかの点から既に呼び出されているため、メソッドをUtilityクラスに移動したくないので、これらすべての場所でこの小さな変更を行い、すべての呼び出しの前にUtilityクラス名を追加します。また、私は不愉快で、GUIクラスへの参照を取得するためにFormクラス以外のメソッドは好きではありません。実際、私は最初にこれをやりたいとは思っていませんでしたが、別のプロジェクトのGUIから別のクラスのものを印刷する必要性が生じました。
追加された 著者 R. Ruiz.,

1 答え

C#3(VS2008)以降を使用していると仮定します。

Utilities.myUtilityMethod(str => TextAppend(myTextBox1, str));

...

public static void myUtilityMethod(Action textAppender)
{
    if (textAppender != null) { textAppender("Hi Worldo!"); }
}

.NET 2.0を使用している場合は、ラムダ式の代わりに匿名メソッドを使用できます。

Utilities.myUtilityMethod(delegate(string str) { TextAppend(myTextBox1, str); });

.NET 1.xを使用している場合は、デリゲートを自分で定義し、名前付きメソッドを使用する必要があります。

delegate void TextAppender(string str);

void AppendToTextBox1(string str)
{
    TextAppend(myTextBox1, str);
}

...

Utilities.myUtilityMethod(new TextAppender(AppendToTextBox1));

...

public static void myUtilityMethod(TextAppender textAppender)
{
    if (textAppender != null) { textAppender("Hi Worldo!"); }
}
13
追加された
完璧!私はラムダ式と無名メソッドの両方をテストし、彼らは完璧に動作します。何もしたくない場合でもnull条件が機能します。どうもありがとうございました!
追加された 著者 R. Ruiz.,