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

时间:2009-09-16 15:28:24

标签: c# reflection

我想知道是否可以使用反射在运行时定位对象?这更像是一个实验,而不是一个实际的要求。

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

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

这甚至可能吗?

7 个答案:

答案 0 :(得分:7)

不,基本上。

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

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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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

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

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

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

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

答案 3 :(得分:0)

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

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,据我所知,你的问题的答案是否

答案 4 :(得分:0)

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

但是,对于更具体的方案,您可以从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;
    }
}

答案 5 :(得分:0)

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

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

对于查找特定实例的一般问题,问题已经回答。

答案 6 :(得分:0)

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

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

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