Remoting и Event'ы
Пишу одно приложение, использующее Remoting и возникла необходимсоть подписать клиена на соытия сервера. Сам по-себе принцип достаточно прост, причем на FW 1.1 все собиралось и работало замечательно, а вот на 2.0 возникли проблемы. Приблизительная реализация такая: создаем класс событий
| [Serializable] public class ScreenEventArgs : EventArgs { private byte[] _screenState; public byte [] ScreenState { get { return _screenState; } set { _screenState = value; } } public ScreenEventArgs(Bitmap ScreenState) { // констуктов } } |
Делегат
public delegate void ScreenEventHandler(object sender, ScreenEventArgs args); |
И непосредственно интерфейс
| public interface IScreenWatcher { event ScreenEventHandler ScreenEvent; bool GetScreen(string Name, string Password, int Interval); } |
Уведомление клиентов выглядит так:
| private void NotifyClients(ScreenEventArgs args) { if(ScreenEvent == null) { return; } Delegate[] invkList = ScreenEvent.GetInvocationList(); IEnumerator iE = invkList.GetEnumerator(); while(iE.MoveNext()) { ScreenEventHandler handler = (ScreenEventHandler) iE.Current; try { IAsyncResult aResult = handler.BeginInvoke(this, args, null, null); } catch { ScreenEvent -= handler; } } } |
Ну, а подписывание клиента производится следующим образом:
| IScreenWatcher _iScreenWatcher = Activator.GetObject(typeof (IScreenWatcher), Client.ScreenViewerAddress) as IScreenWatcher; // Подписываемся на событие _iScreenWatcher.ScreenEvent += new ScreenEventHandler(OnScreenChange); |
Где, OnScreenChange
| public void OnScreeChange(object sender, ScreenEventArgs args) { // Реализация реакции на событие } |
Вот основная проблема заключалась в том, что в момент подписки на событие выкидывалось исключение, сообщаюшее, что данная операция невозможна с текущи уровнем безопасности. Оказалось, что при создании TcpChannel'a необходимо было понизить уровень безопасности, например, таким образом:
| for (int ii = 0; ii < _plugInfo.Count; ii++) { IDictionary props = new Hashtable(); props["name"] = _plugInfo[ii].Name; // Имя канала -- не должно быть одинаковых props["port"] = Server.StartPort + ii + 1; // Порт BinaryServerFormatterSinkProvider bsf = new BinaryServerFormatterSinkProvider(); bsf.TypeFilterLevel = TypeFilterLevel.Full; // Вот как раз эта строчка и понижает уровень безопасности TcpChannel tcpCh = new TcpChannel(props, null, bsf); ChannelServices.RegisterChannel(tcpCh, true); } |
