【问题标题】:use/need of Reflection使用/需要反射
【发布时间】:2012-12-27 20:47:01
【问题描述】:

我在这个论坛中搜索了这些问题并找到了很好的资源。为了理解反射的概念,我自己编写了以下代码。

static void Main(String[] args)
    {

        MyClass1 mc1 = new MyClass1();
        Type t = mc1.GetType();
        MethodInfo mInfo = t.GetMethod("method1");
        object[] o=new object[]{2};
        Console.WriteLine(mInfo.Invoke(mc1, o));
        NameSpace2.Class1 c1 = new NameSpace2.Class1();
        Type t2 = c1.GetType();
        MethodInfo[] mI2 = t2.GetMethods();
        object[] o2 = new object[] {2,3};
        foreach (MethodInfo m in mI2)
        {
            Console.WriteLine(m);
        }

        object x = Activator.CreateInstance(t);

        Console.WriteLine(x.GetType());
        Console.Read();

    }

我了解通过反射,我将能够在运行时获取有关对象的类型、公共方法、属性的信息,并且还能够创建该类型的对象。但我的观点是,除非并且直到我知道方法需要作为输入的参数是什么,否则我将无法实现任何方法,并且这些信息仅在运行时可用。那么,反射的重要性是什么,仅仅是关于一个对象的信息吗?

【问题讨论】:

  • 例如你可以从文件中读取字符串“method1”吗?
  • ORM 和数据绑定是反射之美的好例子。
  • 你有没有想过VisualStudio的属性窗口是如何实现的?我认为没有猴子会为他们添加的每个对象输入编辑器窗口! --我的意思不是不尊重,只是一个说明性的笑话:)

标签: c# .net reflection


【解决方案1】:

如果你需要反射,那么你的需求不能在编译时解决,而是在运行时解决。

  • 假设您正在制作一个需要模块化的酷应用程序,您让开发人员为您的应用程序编写插件。 您无法为可能创建的每个插件编译应用程序。然后你需要通过反射加载、内省和调用插件的对象。

  • 假设您正在为银行应用程序制作中间件,该中间件负责处理数据库连接并使用该数据执行一些业务逻辑。您可以为每个可用的数据库编写和编译中间件。或者您可以编写一次代码,然后在运行时激活并使用正确的数据库驱动程序。

  • 如果您想动态获取 WebService 的 WSDL、生成代理并在代理编译并加载到内存后立即使用 Web 服务怎么办?在编译时想不出办法。

  • 更好的是,如果您使用 CodeDOM 生成代码、编译、加载已编译的程序集并使用您刚刚编译的对象会怎样?

有一天你会需要使用反射。我希望如此...

【讨论】:

    【解决方案2】:

    除了 Adrian Salazar 的回答之外,我还有一些过去几年遇到的例子:

    • 自动包装器生成。我编写了一个使用 OpenGL/OpenAL 的跨平台框架,为了简单起见,我使用了在设备可用后初始化的委托。在 iOS 上,我需要将每个方法声明为带有 dll-import 属性的外部方法。 OpenGL/OpenAL 有很多方法,所以我只编译了委托,编写了一个程序,它给我写了一个声明所有这些方法的 *.cs 文件。现在,这可以让我在一周的痛苦工作中保持这个包装器的最新状态。
    • 代理生成。 我曾经写过一个应用程序,它必须能够处理 Flash 对象并在 PropertyInspector 中显示它们的属性并调用对象的方法,为了能够做到这一点,我写了一个 IL 生成器并使用反射来反射属性并调用方法。
    • 最常见的示例应该是:加载和保存数据。此任务主要通过使用反射来完成。我在 2012 年年中编写了一个 xml-reader/writer,它允许像在 XAML 中那样初始化对象,然后再次将这些对象保存到 XML 中。对象初始化并将它们再次写回 XML 是一项任务,如果您不使用反射,这将导致大量工作。

    如您所见,有很多例子证明反射确实有用。在过去的 8 年中,我多次使用反射,我什至无法计算使用次数。

    【讨论】:

      【解决方案3】:

      回答你隐含的问题。

      但我的意思是,除非并且直到我知道方法需要作为输入的参数是什么,否则我将无法实现任何方法,并且这些信息仅在运行时可用。

      我们举一个简单的例子。我想在一个需要参数的类上实例化一个方法,我将成为促进者(即我将创建类并启动该方法,但我对此一无所知)。

      public class Foo
      {
          public Foo() { }
      
          public void FooMethod(string parm) { }
      }
      
      public class Facilitator
      {
          public void RaiseAction(string type, string action, params object[] parm)
          {
              var o = Activator.CreateInstance("MyAssembly", type);
              var methodInfo = o.GetType().GetMethod(action);
              if (methodInfo == null) { return; }
              methodInfo.Invoke(o, parm);
          }
      }
      

      现在,在上面的示例中,我只是将参数传递给一个我一无所知的对象的方法。

      现在,让我们来看看反射可以实现的其他一些事情。让我们想象一下,我需要联系private 成员 - 尽管通常是个坏主意 - 如果有必要我可以这样做,有时我会这样做以调试 以进行黑客攻击.您是否曾经想要一个在运行时无法到达的标志来帮助您做出决定?您在调试器中看到了标志,但它隐藏在对象层次结构中并且它是private 来启动!更糟糕的是?微软表示他们将在后续版本中以某种方式公开它,但你现在需要走出门,你需要这个标志!或者你可能需要这个方法!

      考虑这个例子(o 是一些你需要的对象,它是私有的):

      var propertyInfo = o.GetType().GetProperty("SomePublicProperty");
      if (propertyInfo == null) { return; }
      var myFirstPrivateMember = propertyInfo.PropertyType.GetField("_somePrivateField", BindingFlags.Instance | BindingFlags.NonPublic);
      

      哦,哦,我们刚刚获得了我们的第一个 private 成员 - 还有一个字段!

      反射对我来说很重要,因为我已经构建了许多完全动态的应用程序,从数据库一直到用户体验。当你构建这样的应用程序时,你对任何事情都一无所知——你没有配置它——但由于反射的灵活性,你可以InvokeGet 任何你想要或需要完成工作的东西。

      就像其他任何事情一样,这些都是非常反射的简单示例,但希望您能很好地了解反射的力量以及它为何有用。在您的世界非常静态的大多数日常应用程序中,您可能永远不会使用它,但稍微扩展一下并变得更加动态,您就会需要它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-21
        • 2018-12-12
        • 2014-02-08
        • 2018-09-12
        • 1970-01-01
        • 1970-01-01
        • 2015-09-23
        相关资源
        最近更新 更多