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