具有不同定义的方法字典

时间:2020-10-26 04:26:45

标签: .net dictionary delegates

我有大量的第三方API类(23个和计数中的),我需要创建一些测试调用以将现有调用用作代理(因为没有定义的专用测试调用),例如GetTitles()GetCountries()

到目前为止,我已经在每个API的命名空间下复制了大约20行代码,这显然会带来很多维护问题。但是我想将此简化为一个方法,该方法位于每个(部分)API类继承的类中。

这意味着每个API /类都将通过继承的Helper类向其添加一个TestConnection()方法。然后,TestConnection()方法需要知道要调用哪个代理测试调用。 (我已经确定了调用类,因此可以确定使用this.GetType()等进行哪个调用,产生“ Api1”,“ Api2”等。)

我还阅读了有关使用委托动态地进行代理测试调用的信息。

但是...

我想将这些委托放入TestCalls字典(由字符串调用方,TestCall委托组成)中,其中TestCall是已定义的委托,并像这样调用它们:

TestCalls[caller].Invoke()

但是,问题有两个:

  1. 并不是所有的代理调用在参数和返回类型*上都具有相同的签名,并且
  2. 到目前为止,至少有一个代理调用需要一个字符串参数(其他代理调用,尽管它们既没有参数也没有可选参数,但我不使用它们进行调用)。

(*因为我对返回值不感兴趣,所以无论调用是否成功,我都可以使用object作为所有调用的返回类型。)

最初,我有这个:

private delegate object TestCall();
private static Dictionary<string, TestCall> TestCalls = new Dictionary<string, TestCall>();

TestCalls.Add("Api1", Api1.GetTitles);
TestCalls.Add("Api2", Api2.GetCountries);
TestCalls.Add("Api3", Api3.GetCurrencies);
TestCalls.Add("Api4", Api4.GetNameFormats);

但这不能编译,因为方法签名不相同(而且我无法控制这些签名)。

因此,在反复研究和深入了解之后,我最终创建了几个不同的委托定义,并分别添加了代理调用,例如:

private delegate object TestCall1();
private delegate object TestCall2(bool? a1);
private delegate object TestCall3(int? a1, string a2, bool? a3);
private static Dictionary<string, Delegate> TestCalls = new Dictionary<string, Delegate>();

TestCalls.Add("Api1", new TestCall1(Api1.GetTitles));
TestCalls.Add("Api2", new TestCall1(Api2.GetCountries));
TestCalls.Add("Api3", new TestCall2(Api3.GetCurrencies));
TestCalls.Add("Api4", new TestCall3(Api4.GetNameFormats));

这有效(除了需要将参数值添加到一个我真的想避免的调用中)。

但是它比我所希望的要复杂得多。

我研究过使用定义的Func委托,代表方法的原始字符串等,似乎没有什么比我想要的优雅/可维护/直观。

有人对“泛化”代理呼叫代表有任何建议吗?还是完全不同的方法?

理想情况下,我将能够拥有一个显式代理调用的字典,包括诸如Api5.GetSomething("StringArg")Api6.GetAnother(IntArg)之类的任何自变量,因此我不必在调用块中有条件地添加它

顺便说一句,对我来说,如果参数是可选的,则强制执行参数提供/编号是没有意义的;当我手动调用带有可选参数的方法并且不提供它们时,一切都很好。为什么要使用委托人施加压力?

1 个答案:

答案 0 :(得分:0)

这就是我最终得到的:

class ApiHelper
{
    private static Dictionary<string, string> TestCalls= new Dictionary<string, string>();

    static ApiHelper()
    {
        TestCalls.Add("Api1", "GetTitles");
        TestCalls.Add("Api2", "GetCountries");
        TestCalls.Add("Api3", "GetCurrencies");
        TestCalls.Add("Api4", "GetNameFormats");
        ...

    bool TestConnection()
    {
        string caller = GetType().FullName.Split(new char[] {'.'})[1]; // Api1, Api2, ...
        try
        {
            MethodInfo oMethod = GetType().GetMethod(TestCalls[caller]);
            object[] params = new object[method.GetParameters().Length];
            if (caller == "Api2") params[0] = "AnArg"; // Add an argument to this call
            var result = oMethod.Invoke(this, params);
            TestConnectionMsg = $"The API connection test passed.";
            return true;
        }
        catch (Exception x)
        {
            TestConnectionMsg = $"The API connection test failed: {x.Message}.";
            return false;
        }
    }
}

此代码派生测试调用的必需项-可选! -调用期望并进行调用的参数列表,直至成功或失败,直至catch块。

这不是我一直在寻找的最优雅的解决方案,但是它可以正常工作并且足够强大。

相关问题