如何解决具有不同定义的方法字典
我有大量的第三方API类(23个和计数中的),我需要创建一些测试调用以将现有调用用作代理(因为没有定义的专用测试调用),例如GetTitles()
, GetCountries()
等
到目前为止,我已经在每个API的命名空间下复制了大约20行代码,这显然会带来很多维护问题。但是我想将此简化为一个方法,该方法位于每个(部分)API类继承的类中。
这意味着每个API /类都将通过继承的Helper
类向其添加一个TestConnection()
方法。然后,TestConnection()
方法需要知道要调用哪个代理测试调用。 (我已经确定了调用类,因此可以确定使用this.GetType()
等进行哪个调用,产生“ Api1”,“ Api2”等。)
我还阅读了有关使用委托动态地进行代理测试调用的信息。
但是...
我想将这些委托放入TestCalls
字典(由字符串调用方,TestCall委托组成)中,其中TestCall
是已定义的委托,并像这样调用它们:
TestCalls[caller].Invoke()
但是,问题有两个:
(*因为我对返回值不感兴趣,所以无论调用是否成功,我都可以使用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)
之类的任何自变量,因此我不必在调用块中有条件地添加它
顺便说一句,对我来说,如果参数是可选的,则强制执行参数提供/编号是没有意义的;当我手动调用带有可选参数的方法并且不提供它们时,一切都很好。为什么要使用委托人施加压力?
解决方法
这就是我最终得到的:
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块。
这不是我一直在寻找的最优雅的解决方案,但是它可以正常工作并且足够强大。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。