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

C#反射:是否可以在运行时找到对象的实例?,c#,reflection,C#,Reflection,我想知道是否可以在运行时使用反射来定位对象?这与其说是实际要求,不如说是实验 我在一个对象实例上使用了.GetType()方法来对该对象执行各种操作,但我的问题是:如果我知道某个类型的对象在运行时存在,但我不能按名称引用它,该怎么办 作为一个更具体的例子,假设我有一个加载DLL的WinForms应用程序——DLL如何独立地定位对表单对象的引用,以便与表单交互,或者调用公共方法 这可能吗?基本上不可能 你可能会有一些可怕的全局映射,从类型到“我感兴趣的类型的实例”,但除此之外,没有 基本上,Win

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

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

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

这可能吗?

基本上不可能

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


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

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

我不理解您的问题。引用对象时,是指搜索对象实例,还是指搜索对象类型

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

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

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


编辑:忘记您知道类型的名称。您还可以使用
Assembly.GetType(字符串名称)

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

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

更新:顺便说一句,据我所知,你的问题的答案是否定的,因为其他人已经回答了,不,这在一般情况下是不可能的

但是,对于更具体的场景,您可以从WinAPI中获得所有窗口的列表,然后检查每个窗口的属性

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;
    }
}
公共静态类帮助器
{
公共静态IntPtr[]GetToLevel Windows()
{
列表窗口列表=新列表();
GCHandle=GCHandle.Alloc(windowList);
尝试
{
Helper.EnumWindows(Helper.EnumWindowsCallback,(IntPtr)句柄);
}
最后
{
handle.Free();
}
返回windowList.ToArray();
}
私有委托bool EnumWindowsCallBackDelegate(IntPtr hwnd、IntPtr lParam);
[DllImport(“user32.Dll”)]
私有静态外部int EnumWindows(EnumWindowsCallBackDelegate回调,IntPtr lParam);
私有静态bool EnumWindowsCallback(IntPtr hwnd、IntPtr lParam)
{
((List)((GCHandle)lParam.Target).Add(hwnd);
返回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/调用
EnumWindows
或使用
Form.FromHandle()

这真是一条漫长的路。
Application
对象维护其
OpenForms
集合(用于WinForms应用程序)中的所有内容。
Form f = Application.OpenForms.Where(x => x.GetType().Name == "FormIWant").FirstOrDefault();