1

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

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();

    }

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

4

3 回答 3

3

如果您需要反射,那么您的需求无法在编译时解决,而是在运行时解决。

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

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

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

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

有一天,您将需要使用反射。但愿如此...

于 2012-12-27T12:26:20.660 回答
1

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

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

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

于 2012-12-27T12:47:01.337 回答
0

谈谈你隐含的问题。

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

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

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成员——而且还有一个领域!

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

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

于 2012-12-27T12:25:43.023 回答