6

可変数の引数を取るメソッドがあると仮定しましょう:

void Target( params object[] args );

これを具体的なパラメーター リストを持つアクションにアタッチするには、ラムダ式を作成します。

Action<int, int> someAction += (a, b) => Target(a, b);

このラムダ式を動的に作成して、ハンドラーを任意のタイプのイベントにアタッチできる可能性はありますか? 何かのようなもの:

someAction += CreateDelegate( typeof(someAction), Target );

使用しようとしましDelegate.CreateDelegateたが、ターゲットが引数の具体的なリストを含むメソッドを提供することを期待しています。私はそれが可能であるべきだと感じていますExpression.Lambdaが、今のところ私は成功していません. アイデアはありますか?

編集

イベントの名前をアクションに、ハンドラーをターゲットに変更しました。

4

2 に答える 2

6

このメソッドのデリゲート:

void Handle( params object[] args );

デリゲートは修飾子Action<object[]>を使用できないため、 になります。paramsコンパイラが行うことを行い、他のメソッドをオブジェクト配列にマップする必要があります。

キーワードはコンパイラによって処理されるparamsため、ランタイムはメソッドを通常のオブジェクト配列を受け取るかのように使用します。これを行うには、適切なリストのオブジェクト配列を作成し、それにオブジェクトを設定してから、それを行うメソッドをハンドラーにアタッチする必要があります。

于 2012-10-22T16:07:58.083 に答える
3

次の行を分析して、ラムダの背後にある式を調べました。

Expression<Action<int, int>> ex = (a, b) => Target(a, b);

これに基づいて、独自のデリゲート ファクトリを作成しました。

public static Delegate CreateDelegate( Type delegateType, Action<object[]> target )
{
    var sourceParameters = delegateType.GetMethod("Invoke").GetParameters();

    var parameters = sourceParameters.Select( p => Expression.Parameter( p.ParameterType, p.Name ) ).ToArray();

    var castParameters = parameters.Select(p => Expression.TypeAs(p, typeof(object))).ToArray();

    var createArray = Expression.NewArrayInit(typeof(object), castParameters);

    var invokeTarget = Expression.Invoke(Expression.Constant(target), createArray);

    var lambdaExpression = Expression.Lambda( delegateType, invokeTarget, parameters);

    return lambdaExpression.Compile();
 }
于 2012-10-22T23:17:54.333 に答える