2

以下を動的に実行しようとする小さな関数を作成しました。

        Func<object, object> fa = i => Convert.ChangeType(i, typeof (string));
        Func<int, string> fb = o => (string) fa((int)o);

機能は次のとおりです。

    /// <summary>
    ///     Converts <see cref="Func{object, object}" /> to <see cref="Func{T, TResult}" />.
    /// </summary>
    public static Delegate Convert(Func<object, object> func, Type argType, Type resultType)
    {
        Contract.Requires(func != null);
        Contract.Requires(resultType != null);

        var param = Expression.Parameter(argType);

        var converted = Expression.Convert(
            Expression.Call(func.Method, Expression.Convert(param, typeof (object))),
            resultType);

        var delegateType = typeof (Func<,>).MakeGenericType(argType, resultType);
        return Expression.Lambda(delegateType, converted, param).Compile();
    }

これで、クロージャーが関与していない場合に問題なく動作します - このテストはパスします:

    [Test]
    public void When_Converting_Without_Closure_Then_Suceeds()
    {
        // Arrange
        Func<object, object> f = i => Convert.ChangeType(i, typeof(string));            
        var sut = FuncConversion.Convert(f, typeof(int), typeof(string));

        // Act
        var res = (string) sut.DynamicInvoke(10);

        // Assert
        Assert.AreEqual(typeof(Func<int, string>), sut.GetType());
        Assert.AreEqual("10", res);
    }

しかし、クロージャーが関係している場合、このテストは失敗します:

    [Test]
    public void When_Converting_With_Closure_Then_Succeeds()
    {
        // Arrange
        var typeTo = typeof (string);
        Func<object, object> f = i => Convert.ChangeType(i, typeTo);            
        var sut = FuncConversion.Convert(f, typeof(int), typeof(string));

        // Act
        var res = (string)sut.DynamicInvoke(10);

        // Assert
        Assert.AreEqual(typeof(Func<int, string>), sut.GetType());
        Assert.AreEqual("10", res);
    }

System.ArgumentException : 静的メソッドには null インスタンスが必要です。非静的メソッドには非 null インスタンスが必要です。パラメーター名: System.Linq.Expressions.Expression.ValidateStaticOrInstanceMethod(Expression インスタンス、MethodInfo メソッド) のメソッド System.Linq.Expressions.Expression.Call(MethodInfo メソッド、式 arg0) のメソッド

何が間違っているのですか?

4

1 に答える 1