Я хотел бы создать динамический прокси-сервер для привязки элементов управления WinForms к объектам, измененным другим (не GUI) потоком. Такой прокси будет перехватывать событие PropertyChanged и отправлять его, используя соответствующий SynchronizationContext.
Таким образом, я мог бы использовать вспомогательный класс для выполнения работы без необходимости каждый раз выполнять синхронизацию вручную (if (control.InvokeRequired) etc.
).
Есть ли способ сделать это с помощью LinFu, Castle или подобной библиотеки?
[Изменить]
Источник данных не обязательно является списком. Это может быть любой бизнес-объект, например ::
interface IConnection : INotifyPropertyChanged
{
ConnectionStatus Status { get; }
}
Я мог бы создать оболочку, которая могла бы выполнять работу, и это выглядело бы примерно так:
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;
}
(могут быть некоторые ошибки в этом коде, я делаю это)
Я хотел бы иметь для этого динамический прокси (Reflection.Emit), один лайнер, например,
IConnection syncConnection
= new SyncPropertyChangedProxy<IConnection>(actualConnection);
и я хотел знать, возможно ли что-то подобное с использованием существующих реализаций динамического прокси.
Более общий вопрос: Как перехватить событие при создании динамического прокси? Перехват (переопределение) свойств хорошо объясняется во всех реализациях.
[Edit2]
Причина (я думаю) мне нужен прокси в том, что трассировка стека выглядит так:
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)
Вы можете видеть, что BindToObject.PropValueChanged
не передает экземпляр sender
в PropertyManager
, и Reflector показывает, что на объект отправителя нигде не ссылаются. Другими словами, когда срабатывает событие PropertyChanged
, компонент будет использовать отражение для доступа к свойству исходного (связанного) источника данных .
Если бы я обернул свой объект в класс, содержащий только событие (как предложено Сэм ), такой класс-обертка не будет содержать никаких свойств, к которым можно получить доступ через Reflection.