3

次のようなかなりの数のパラメーターを取るデリゲートがあります。

public delegate void MyDelegate(float thereAre, int lotsOf, string parametersIn, int thisDelegate);
public MyDelegate theDelegateInstance;

Visual Studio 2010 には、メソッドがデリゲート シグネチャと一致するのを支援するオート コンプリート機能がないため、これは非常に面倒です。私は基本的に、デリゲートのパラメーターの一部のみを (またはまったく) 取り、他のパラメーターを無視するメソッドを作成できるようにしたいと考えています。

theDelegateInstance += delegate()
{
    Debug.Log("theDelegateInstance was called");
};

または

theDelegateInstance += delegate(float thereAre, int lotsOf)
{
    if(thereAre > lotsOf) Debug.Log("thereAre is way too high");
};

メソッドがデリゲートを取り、それを次のように呼び出す MyDelegate を返すようにできることがわかりました。

public delegate void VoidMethod();

public static MyDelegate ConvertToMyDelegate(VoidMethod method)
{
    return delegate(float thereAre, int lotsOf, string parametersIn, int thisDelegate)
    {
        method();
    };
}

しかし、そのためには、異なる変換ごとに静的メソッドを宣言する必要があります。

目的の結果を得るために、パラメーターなしで最初の例を実行できることがわかりました。

theDelegateInstance += delegate//Notice that there are no brackets here.
{
    Debug.Log("theDelegateInstance was called");
};

ただし、これはパラメーターを取らないインライン メソッドでのみ機能します。2 番目の例のように、パラメーターを 1 つでも使用したい場合は、すべてのパラメーターが必要になります。

4

3 に答える 3

1

基本的に、あなたが求めているのは、次のようなラムダを返すメソッドです:

public static MyDelegate ConvertToMyDelegate(VoidMethod method)
{
    return (thereAre, lotsOf, parametersIn, thisDelegate) => method();
}

幸いなことに、.Net にはプログラムでラムダを作成する方法が含まれています。Convertこれは、両方のデリゲート型で任意の数のパラメーターを処理するジェネリック メソッドを 1 つだけ作成できることを意味します。

public static TTarget ConvertDelegate<TSource, TTarget>(TSource sourceDelegate)
{
    if (!typeof(Delegate).IsAssignableFrom(typeof(TSource)))
        throw new InvalidOperationException("TSource must be a delegate.");
    if (!typeof(Delegate).IsAssignableFrom(typeof(TTarget)))
        throw new InvalidOperationException("TTarget must be a delegate.");
    if (sourceDelegate == null)
        throw new ArgumentNullException("sourceDelegate");

    var parameterExpressions = typeof(TTarget)
        .GetMethod("Invoke")
        .GetParameters()
        .Select(p => Expression.Parameter(p.ParameterType))
        .ToArray();

    var sourceParametersCount = typeof(TSource)
        .GetMethod("Invoke")
        .GetParameters()
        .Length;

    var expression = Expression.Lambda<TTarget>(
        Expression.Invoke(
            Expression.Constant(sourceDelegate),
            parameterExpressions.Take(sourceParametersCount)),
        parameterExpressions);

    return expression.Compile();
}
于 2013-06-07T18:52:14.320 に答える