2009-09-16 25 views
5

Me pregunto si es posible utilizar la reflexión para localizar un objeto en tiempo de ejecución. Esto es más un experimento que un requisito práctico.C# Reflection: ¿Es posible encontrar una instancia de un objeto en tiempo de ejecución?

He utilizado el método .GetType() en una instancia de objeto para hacer varias cosas al objeto, pero mi pregunta es: ¿qué ocurre si sé que existe un objeto de cierto tipo en tiempo de ejecución, pero no puedo referirse a él por su nombre.

Como ejemplo más concreto, supongamos que tengo una aplicación WinForms que carga una DLL: ¿cómo podría esa DLL localizar de manera independiente una referencia al objeto de formulario para interactuar con el formulario o llamar a un método público?

¿Esto es posible?

Respuesta

7

No, básicamente.

Puede tener algún tipo de horrible mapa global del tipo de "la instancia del tipo que me interesa", pero de lo contrario, no.

Básicamente, la aplicación WinForms debe pasar una referencia al formulario en la DLL de alguna manera.

1

No, esto no es posible, porque las referencias son implementadas de forma privada por Microsoft, no son punteros en comparación con C/C++, en C/C++ antiguo puede escanear su memoria, pero en .NET no existen tales herramientas.

0

No entendí su pregunta. Cuando se refiere a un objeto, ¿quiere decir que está buscando una instancia de objeto, o se refiere a buscar un tipo de objeto?

En caso de que esté buscando una instancia, la respuesta es no. Si busca un tipo por nombre en tiempo de ejecución, la respuesta es sí.

La siguiente línea le permitirá obtener todos los ensamblados cargados en el dominio de la aplicación: AppDomain.CurrentDomain.GetAssemblies();

El método de instancia Assembly.GetTypes() obtendrá todos los tipos en un ensamblaje.

Editar: Olvidaste que sabías el nombre del tipo. También puede usar Assembly.GetType(string name).

0

Puede diseñar un marco de plugin para su aplicación. He aquí un ejemplo:

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. 
} 

entonces usted puede encontrar sus complementos cuando se carga un ensamblado en tiempo de ejecución.

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

Updatd: Por cierto, por lo que yo sé la respuesta a su pregunta es no

0

Como otros han respondido ya, no, no es posible de una manera general.

Pero, para un escenario más específico, podría obtener una lista de todos los Windows de Win API y luego examinar cada uno de las propiedades que está tratando de buscar.

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; 
    } 
} 
+0

Eso es realmente * * el camino más largo. El objeto 'Application' mantiene todos aquellos en su colección' OpenForms' (para aplicaciones WinForms). –

0

Si usted apenas está experimentando y tratando de localizar el formulario principal de la DLL que podría hacer:

//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; 

Acabamos probado que por assemblys dependientes, no para carga dinámica queridos. Pero podría valer la pena intentarlo.

Para la cuestión general de localizar una instancia específica, la pregunta ya ha sido respondida.

0

Jon Skeet tiene razón en que no es posible para cualquier tipo arbitrario.

Para su ejemplo concreto, es posible. Y que no es necesario p/invocar o utilizar EnumWindowsForm.FromHandle()

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