c# - 何时使用反射而不是引用程序集
问题描述
我在 .NET Framework 中创建了一个 dll,现在在另一个项目中使用它。我找到了两种使用我的 dll 的方法。
通过在我的项目引用中引用 dll 并创建一个实例
通过使用反射
我的 DLL
namespace MathHelper
{
public class Helper
{
public int add(int a, int b)
{
return a + b;
}
}
}
我的程序
static void Main(string[] args)
{
//Using referenced dll in project
Helper helper = new Helper();
Console.WriteLine(helper.add(4,5));
//Using Reflection
Assembly assembly = Assembly.LoadFile(@"C:\Users\myUser\source\repos\TestMathHelper\TestMathHelper\bin\Debug\MathHelper.dll");
Type type = assembly.GetType("MathHelper.Helper");
object instance = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod("add");
int result = (int)method.Invoke(instance, new object[] {4, 5});
Console.WriteLine(result);
Console.ReadKey();
}
两个结果都有效并显示为 9。
我应该更喜欢哪种方法?什么时候应该使用反射,什么时候不应该?反射的优点是什么?
解决方案
如果可能的话,我们想编写类型安全的代码,编译器会告诉我们是否调用了实际存在的方法,是否传递了正确的参数等。这样,如果出现问题,代码就会获胜甚至没有编译,我们甚至在尝试运行我们的代码之前就发现了问题。
用反射查看代码,这里有一些可能出错的地方。在每种情况下,如果我们使用引用的程序集和强类型对象和方法,编译器都会捕捉到这一点并警告我们。使用反射可以编译代码,但在运行程序之前我们不会发现问题:
// The assembly might not be there. Or we can't load it.
Assembly assembly = Assembly.LoadFile(@"C:\Users\myUser\source\repos\TestMathHelper\TestMathHelper\bin\Debug\MathHelper.dll");
// The assembly doesn't have a type with that name.
Type type = assembly.GetType("MathHelper.Helper");
// The type doesn't have a constructor with no arguments.
object instance = Activator.CreateInstance(type);
// The type doesn't have a method called "add".
MethodInfo method = type.GetMethod("add");
// The "add" method doesn't take two ints as arguments or doesn't return an int.
int result = (int)method.Invoke(instance, new object[] {4, 5});
更不用说对于我们或接下来的开发人员来说,能够键入类名并让我们的 IDE 建议方法和属性的名称真是太棒了。否则,我们每次都必须查看其他类的源代码或文档,以了解它的成员是什么、它需要什么参数、这些参数的含义以及它返回的内容。
在特定类型未知且不那么重要的情况下,反射通常会更好。
例如,我们可以编写一个方法,该方法接受某个对象的List<T>
位置T
,然后它读取每个实例的所有公共属性并将它们全部写入 CSV 文件。
public void WriteToCsv<T>(IEnumerable<T> items, StreamWriter writer)
在这种情况下,我们不会编写处理特定类型的方法。我们并不真正关心类型是什么。不管T
是什么,我们都会使用反射来找出它的公共属性是什么。然后我们将使用这些属性来获取每个项目的相应值。
这是一个过度概括。使用反射有很多有效的案例。我们应该避免在处理已知类型时使用它,并且有一种方法可以在没有反射的情况下做我们想做的事情。如果我们把自己画到一个角落,看起来我们需要使用反射,那么也许我们可以修复部分设计。或者,如果我们认为我们需要反思,我们可以得到另一双眼睛。我之所以这么说,是因为虽然反射很有用,但它在许多不必要的情况下被使用,并且使代码更加脆弱和难以理解。
推荐阅读
- python - Pandas:TypeError:列表索引必须是整数或切片,而不是 DataFrame
- pagination - 使用 Azure 数据工厂从 HubSpot REST api 获取数据 - 所有联系人(分页)
- python - 如何获取和解码发往特定端口的消息
- sql-server - 用户“域\用户”登录失败。原因:试图将 NT 帐户名用于 SQL Server 身份验证。[客户:
] - java - 用指数符号Java解析复数
- pandas-groupby - 按日期计数的 Pandas 列
- php - 无法在PHP中移动文件夹中的文件
- git - tilda 和 caret 符号对 git 中的 HEAD 有什么作用?
- tfs - 如何检索 Azure DevOps Wiki 页面列表以进行编辑?
- ios - isIdleTimerDisabled = true 有效,但设置回 false 不会再次使屏幕变暗