创建一个泛型函数的委托

3

我正在编写一些单元测试,其中有很多形如以下的函数:

public void SomeTestHelperMethod<TKey, TValue>(TKey key, TValue value)

我正在反复调用这个函数,并使用不同的参数,就像这样。
SomeTestHelperMethod<int, int>(0, 1);
SomeTestHelperMethod<int, object>(1, new Nullable<double>(16.5));
SomeTestHelperMethod<int, string>(2, "The quick brown fox jumped over the lazy dog.");
SomeTestHelperMethod<object, int>(new NullReferenceException(), 15);
SomeTestHelperMethod<object, object>(StringComparison.Ordinal, new Version());
SomeTestHelperMethod<object, string>((ushort)3, string.Empty);
SomeTestHelperMethod<string, int>(string.Empty, 195);
SomeTestHelperMethod<string, object>("A string", this);
SomeTestHelperMethod<string, string>("Another string", "Another string");

我希望能编写一个函数,它接受一个Action委托,并可以使用所有不同的参数调用委托。有没有方法可以做到这一点? 答案: 感谢MichaelCG,以下是我最终采取的措施:
private void CallWithKeyAndValue(string methodName)
{
    MethodInfo method = typeof(ObservableDictionaryTest).GetMethod(methodName);
    foreach (KeyValuePair<object, object> kvp in ourKeyValueSet)
    {
        MethodInfo genericMethod = method.MakeGenericMethod(kvp.Key.GetType(), kvp.Value.GetType());
        genericMethod.Invoke(this, new[] { kvp.Key, kvp.Value });
    }
}

我仍然对一种更普遍的方法感兴趣,但这个方法对于我的目的是有效的。


你的意思是说,你可以拥有一个对象列表,并在其上循环,但实际上调用特定的泛型方法? - MichaelGG
类似这样。最终,我想要制作一些比我自己编造的随机参数更好的测试参数,并且我想将其添加到该表单的所有函数中的一个单独位置。目前我的单元测试中有很多重复的代码,我想要摆脱它,但我想要调用的函数(SomeTestHelperMethod)都是通用函数。 - Bryan Anderson
1个回答

6
如果我理解正确,这应该展示了你想要做的事情。其中奥妙在于MakeGenericMethod。
using System;

class Program {
    static void Main(string[] args) {
        var meth = typeof(Program).GetMethod("Meth");
        var items = new[] { 
            new { a = (object)"hi", b = (object)1 },
            new { a = (object)TimeSpan.MaxValue, b = (object)DateTime.UtcNow },
        };
        foreach (var item in items) {
            var gmeth = meth.MakeGenericMethod(item.a.GetType(), item.b.GetType());
            gmeth.Invoke(null, new[] { item.a, item.b });
        }
    }

    public static void Meth<A, B>(A a, B b) {
        Console.WriteLine("<{0}, {1}>", typeof(A).Name, typeof(B).Name);
    }
}

输出:

<String, Int32> 
<TimeSpan, DateTime>

有趣,我会试一试。 - Bryan Anderson
如果你曾经过载SomeTestHelperMethod或将其设为非公共方法,请小心。 - Tinister
这是用于单元测试的,所以我认为我永远不会关心,但知道这一点很好。 - Bryan Anderson
@Tinister,是的,我总是搞砸绑定标志,所以我想让这个示例尽可能简单 :)。 - MichaelGG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接