Me gustaría crear un proxy dinámico para vincular controles de WinForms a objetos modificados por un hilo diferente (no GUI). Tal proxy interceptaría el evento PropertyChanged y lo enviaría utilizando el SynchronizationContext adecuado.Crear un proxy INotifyPropertyChanged para enviar llamadas al hilo de la interfaz de usuario
De esta forma podría usar una clase auxiliar para hacer el trabajo, sin tener que implementar la sincronización manualmente cada vez (if (control.InvokeRequired) etc.
).
¿Hay alguna manera de hacerlo usando LinFu, Castle o una biblioteca similar?
[Editar]
origen de datos no es necesariamente una lista. Puede ser cualquier objeto de negocio, por ejemplo:
interface IConnection : INotifyPropertyChanged
{
ConnectionStatus Status { get; }
}
que podría crear una envoltura que podría hacer el trabajo, y sería algo como esto:
public class ConnectionWrapper : IConnection
{
private readonly SynchronizationContext _ctx;
private readonly IConnection _actual;
public ConnectionWrapper(IConnection actual)
{
_ctx = SynchronizationContext.Current;
_actual= actual;
_actual.PropertyChanged +=
new PropertyChangedEventHandler(actual_PropertyChanged);
}
// we have to do 2 things:
// 1. wrap each property manually
// 2. handle the source event and fire it on the GUI thread
private void PropertyChanged(object sender, PropertyChangedEvArgs e)
{
// we will send the same event args to the GUI thread
_ctx.Send(delegate { this.PropertyChanged(sender, e); }, null);
}
public ConnectionStatus Status
{ get { return _instance.Status; } }
public event PropertyChangedEventHandler PropertyChanged;
}
(puede haber algunos errores en este código, lo estoy inventando)
Lo que me gustaría hacer es tener un proxy dinámico (Reflection.Emit) un liner para esto, por ejemplo
IConnection syncConnection
= new SyncPropertyChangedProxy<IConnection>(actualConnection);
y quería saber si algo como esto era posible utilizando las implementaciones de proxy dinámico existentes.
Una pregunta más general sería: ¿Cómo se intercepta un evento al crear un proxy dinámico? Las propiedades de intercepción (anulación) se explican bien en todas las implementaciones.
[Edit2]
La razón (creo) que necesito un proxy es que el seguimiento de la pila se ve así:
at PropertyManager.OnCurrentChanged(System.EventArgs e) at BindToObject.PropValueChanged(object sender, EventArgs e) at PropertyDescriptor.OnValueChanged(object component, EventArgs e) at ReflectPropertyDescriptor.OnValueChanged(object component, EventArgs e) at ReflectPropertyDescriptor.OnINotifyPropertyChanged(object component, PropertyChangedEventArgs e) at MyObject.OnPropertyChanged(string propertyName)
Se puede ver que BindToObject.PropValueChanged
no pasa la instancia sender
al PropertyManager
, y Reflector muestra que el objeto remitente no se referencia en ninguna parte. En otras palabras, cuando se desencadena el evento PropertyChanged
, el componente utilizará la reflexión para acceder a la propiedad de la fuente de datos original (encuadernada).
Si envolví mi objeto en una clase que solo contenía el evento (como Sam propuesto), dicha clase contenedora no contendría ninguna propiedad a la que se pudiera acceder a través de Reflection.
Véase 'ThreadedBindingList' - se ha repetido aquí en la SO (http://stackoverflow.com/questions/455766/how-do-you -correctly-update-a-databound-datagridview-from-a-background-thread). –