【问题标题】:A Dictionary Of Methods With Different Definitions不同定义的方法词典
【发布时间】:2020-10-26 04:26:45
【问题描述】:

我有一大堆第三方 API 类(23 个并且还在增加),我需要创建一些测试调用以将现有调用用作代理(因为没有定义的专用测试调用),例如 GetTitles()、@987654322 @等

迄今为止,我已经在每个 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),这样我就不必有条件地将它添加到调用块中。

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

【问题讨论】:

    标签: .net dictionary delegates


    【解决方案1】:

    这就是我最终得到的结果:

    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 块。

    这不是我一直在寻找的最优雅的解决方案,但它运行良好且足够强大。

    【讨论】:

      猜你喜欢
      • 2014-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-24
      相关资源
      最近更新 更多