何时使用反射而不是引用程序集

时间:2019-05-07 16:33:39

标签: c# dll reflection .net-assembly

我在.NET Framework中创建了一个dll,现在在另一个项目中使用它。我发现了两种使用dll的方法。

  1. 通过在我的项目“引用”中引用该dll并创建一个实例

  2. 通过使用反射

我的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。

我应该选择哪种方法? 我什么时候应该使用反射,什么时候不使用? 反射的优势是什么?

1 个答案:

答案 0 :(得分:1)

如果可能的话,我们想编写类型安全的代码,其中编译器告诉我们是否正在调用一个实际存在的方法,是否传递正确的参数等。该代码甚至无法编译,并且我们甚至在尝试运行代码之前就已经发现了问题。

通过反射查看代码,这可能会出错。在每种情况下,如果我们使用引用的程序集以及强类型的对象和方法,则编译器将捕获并警告我们。使用反射代码可以编译,但是直到运行程序,我们才发现问题:

        // 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文件。 / p>

public void WriteToCsv<T>(IEnumerable<T> items, StreamWriter writer)

在这种情况下,我们不编写用于处理特定类型的方法。我们真的不在乎类型是什么。无论T是什么,我们都会使用反射来找出其公共属性。然后,我们将使用这些属性来获取每个项目的相应值。

这太笼统了。有许多使用反射的有效案例。当我们处理已知类型时,应该避免使用它,并且有一种方法可以做我们想做的事而无需反思。如果我们将自己绘制到一个角落,并且看起来我们需要使用反射,那么也许我们可以修复设计的一部分。或者,如果我们认为我们需要反思,那么我们可以另辟eyes径。我之所以这么说,是因为尽管反射很有用,但在很多不必要的情况下仍会使用反射,这会使代码更脆弱且更难以理解。