C#reflection:是否可以在运行时找到对象的实例?

我想知道是否可以使用reflection在运行时定位对象? 这更像是实验而非实际要求。

我在对象实例上使用.GetType()方法对对象做了各种各样的事情,但我的问题是:如果我知道某个类型的对象在运行时存在,但是我不能通过它来引用它名称。

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

这有可能吗?

不,基本上。

从类型到“我感兴趣的类型的实例”,你可能会有某种可怕的全局映射,但不然。

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

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

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

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

更新:BTW,据我所知,你的问题的答案是否定的

正如其他人已经回答的那样,不,这是不可能的。

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

 public static class Helper { public static IntPtr[] GetToplevelWindows() { List windowList = new List(); 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)((GCHandle)lParam).Target).Add(hwnd); return true; } } 

如果您只是尝试并尝试从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; 

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

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

Jon Skeet是正确的,任何类型都不可能。

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

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