【问题标题】:C# Reflection: Is it possible to find an instance of an object at runtime?C# 反射:是否可以在运行时找到对象的实例?
【发布时间】:2009-09-16 15:28:23
【问题描述】:

我想知道是否可以在运行时使用反射来定位对象?这与其说是实际要求,不如说是一个实验。

我在对象实例上使用了 .GetType() 方法对对象执行各种操作,但我的问题是:如果我知道某个类型的对象在运行时存在,但我无法引用怎么办?按名字给它。

作为一个更具体的例子,假设我有一个加载 DLL 的 WinForms 应用程序 - 该 DLL 如何独立定位对表单对象的引用以便与表单交互或调用公共方法?

这可能吗?

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    基本上没有。

    你可能有某种可怕的全局映射,从类型到“我感兴趣的类型的实例”,但除此之外,没有。

    基本上,WinForms 应用程序应该以某种方式将对表单的引用传递给 DLL。

    【讨论】:

      【解决方案2】:

      不,这是不可能的,因为引用是由 Microsoft 私下实现的,与 C/C++ 相比,它们不是指针,在旧的 C/C++ 中你可以扫描你的内存,但在 .NET 中没有这样的工具。

      【讨论】:

        【解决方案3】:

        Jon Skeet 是正确的,它不可能用于任意类型。

        对于您的具体示例,这是可能的。而且您不需要 p/invoke EnumWindows 或使用 Form.FromHandle()

        Form f = Application.OpenForms.Where(x => x.GetType().Name == "FormIWant").FirstOrDefault();
        

        【讨论】:

          【解决方案4】:

          我不明白你的问题。当您引用一个对象时,您的意思是您正在搜索一个对象实例,还是您指的是搜索一个对象类型?

          如果您正在寻找一个实例,那么答案是否定的。如果您在运行时按名称查找类型,那么答案是肯定的。

          以下行将允许您获取 AppDomain 中所有已加载的程序集: AppDomain.CurrentDomain.GetAssemblies();

          实例方法Assembly.GetTypes() 将为您获取程序集中的所有类型。

          编辑:忘记了你知道类型的名称。你也可以使用Assembly.GetType(string name)

          【讨论】:

            【解决方案5】:

            您可以为您的应用程序设计一个插件框架。 这是一个例子:

            public interface IPlugin
            {
            void Load(Form mainForm); //Or you can have an interface for you main form that allows your plugin to work with your form.
            }
            

            然后您可以在运行时加载程序集时找到您的插件。

            foreach(var type in assembly.GetTypes())
            {
            if(typeof(IPlugin).IsAssignableFrom(type))
            var plugin=(IPlugin)Activator.CreateInstance(type);
            plugin.Load(_mainForm);
            }
            

            更新:顺便说一句,据我所知,您的问题的答案是否定的

            【讨论】:

              【解决方案6】:

              正如其他人已经回答的那样,不,一般来说不可能。

              但是,对于更具体的场景,您可以从 Win API 获取所有 Windows 的列表,然后检查每个 Windows 的属性。

              public static class Helper
              {
                  public static IntPtr[] GetToplevelWindows()
                  {
                      List<IntPtr> windowList = new List<IntPtr>();
                      GCHandle handle = GCHandle.Alloc(windowList);
                      try
                      {
                          Helper.EnumWindows(Helper.EnumWindowsCallback, (IntPtr)handle);
                      }
                      finally
                      {
                          handle.Free();
                      }
              
                      return windowList.ToArray();
                  }
              
                  private delegate bool EnumWindowsCallBackDelegate(IntPtr hwnd, IntPtr lParam);
              
                  [DllImport("user32.Dll")]
                  private static extern int EnumWindows(EnumWindowsCallBackDelegate callback, IntPtr lParam);
              
                  private static bool EnumWindowsCallback(IntPtr hwnd, IntPtr lParam)
                  {
                      ((List<IntPtr>)((GCHandle)lParam).Target).Add(hwnd);
                      return true;
                  }
              }
              

              【讨论】:

              • 那是真的很长的路要走。 Application 对象维护其 OpenForms 集合中的所有对象(用于 WinForms 应用程序)。
              【解决方案7】:

              如果您只是在试验并尝试从您的 DLL 中找到主窗体,您可以这样做:

              //get the current process
              System.Diagnostics.Process p = System.Diagnostics.Process.GetCurrentProcess();
              
              //get its main windows handle (only works, if the form is already created)
              IntPtr hWnd = p.MainWindowHandle;
              
              //locate the form by its native handle
              System.Windows.Forms.Form f = System.Windows.Forms.Form.FromHandle(hWnd) as System.Windows.Forms.Form;
              

              刚刚测试了依赖程序集,而不是动态加载的程序集。但值得一试。

              对于定位特定实例的一般问题,该问题已经得到解答。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-10-09
                • 1970-01-01
                • 2015-11-01
                相关资源
                最近更新 更多