c# - 当具有相似的方法代码但调用者名称发生变化时使用什么方法?
问题描述
我正在设计一个类,它只是包装了一些方法调用,这些方法调用是另一个类库的一部分。
这是我的班级的样子:
public class MyClass
{
IService Service; //Third Party Library.
public MyClass()
{
// Initialization
}
public string MethodA()
{
Service.MethodA();
return Service.GetResult();
}
public string MethodB()
{
Service.MethodB();
return Service.GetResult();
}
public string MethodC()
{
Service.MethodC();
return Service.GetResult();
}
public string MethodD()
{
Service.MethodD();
return Service.GetResult();
}
}
在反射的帮助下,我在一定程度上重构了上面的代码,如下所示:
public class MyClass
{
IService Service;
public MyClass()
{
// Initialization
}
public string MethodA()
{
return GetResult(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
public string MethodB()
{
return GetResult(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
public string MethodC()
{
return GetResult(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
public string MethodD()
{
return GetResult(System.Reflection.MethodBase.GetCurrentMethod().Name);
}
private string GetResult(string methodName)
{
Service.GetType().GetMethods().FirstOrDefault(x => x.Name == methodName).Invoke(Service, null);
return Service.GetResult();
}
}
我看到的一个缺点是,假设如果正在使用的库将来发布新版本并且方法名称有任何更改,它不会在我使用反射时给出任何编译错误,但在运行时,它会抛出异常。
这种方法有更好的替代解决方案吗?
另外,有什么方法可以在有/没有反射的情况下进一步优化我的代码?
解决方案
您可以将反射缓存MethodInfo
到 aDictionary<string, MethodInfo>
中,这样您就不必每次调用时都查找它MyClass.GetResult(string methodName)
。
public class MyClass
{
private string GetResult(string methodName)
{
if (!_methods.TryGetValue(methodName, out MethodInfo method))
{
method = typeof(IService).GetMethods().FirstOrDefault(x => x.Name == methodName);
_methods.Add(methodName, method);
}
method.Invoke(Service, null);
return Service.GetResult();
}
private static readonly Dictionary<string, MethodInfo> _methods = new Dictionary<string, MethodInfo>();
}
MyClass
此外,您可以使用nameof
表达式消除每个公共方法中的反射。
public class MyClass
{
public string MethodA()
{
return GetResult(nameof(MethodA));
}
}
或者,当然,如果您的第三方依赖项更改了方法的名称,那么您仍然会遇到一个问题,即表现为运行时错误而不是编译时错误。因此,您可以通过使用nameof
on 方法的名称来解决此问题IService
。
public class MyClass
{
public string MethodA()
{
return GetResult(nameof(IService.MethodA));
}
}
现在,如果IService
更改了方法名称,则会出现编译器错误。
这应该比您的示例在性能方面得到更好的优化。除了......你在这一点上得到了什么?on 上的每个公共方法MyClass
仍然必须直接引用它对应的 on 方法IService
。IE,MyClass.MethodA
直接引用IService.MethodA
。那么,为什么不直接调用Service.MethodA
并为自己节省反射的复杂性和性能成本呢?
此外,您担心您的第三方依赖项会更改方法名称以及创建运行时错误而不是编译时错误,此处概述的方法应该可以解决这个问题。但是,如果您的第三方依赖项更改了方法的签名怎么办?EG,IService.MethodA()
变成IService.MethodA(string param1)
? 现在你又回到了运行时异常而不是编译器错误的问题上。
我知道您发布的内容只是一个示例,仅基于示例,我无法理解您尝试做的事情的完整背景。但是,基于那个例子,我认为最好MyClass
的版本是没有反射的版本。我真的很难看到通过使用反射调用IService
而不是直接调用方法来获得什么。
推荐阅读
- flutter - 如果我们的小部件树中只有 StatelessWidget,我们就不需要 Keys 了吗?
- c# - 安装后使用 Wix 更新 app.config#
- swift - 是否可以在#selector 中使用数组条目?
- rust - 'std::cmp::PartialEq' 的实现不够通用
- c - 使用 scanf 处理具有结构的多个数据
- pentaho-spoon - Pentaho 数据集成 - 确保一个步骤将在另一个步骤之前运行
- docker - 有没有办法在没有 docker-swarm-mode 的情况下使用 docker-compose 文件连接 2 个 docker
- google-cloud-platform - 如何联系 Google 以请求 GCP 的特殊权限?
- c# - .Net Core/MVC 多租户属性路由使用区域在不同控制器之间具有重复路由
- ios - 从 swift 3 更改后,Sqlite 数据库 swift 4.2 中没有此类表错误