using System.Collections.Generic; using System.ServiceModel; using WeatherService.Devices; using WeatherService.Values; namespace WeatherService.Remote { [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)] public class WeatherServiceDuplex : IWeatherServiceDuplex { private static readonly List Subscribers = new List(); public List GetDevices() { return WeatherServiceCommon.GetDevices(); } public ReadingBase GetLatestReading(string deviceAddress, WeatherValueType valueType) { return WeatherServiceCommon.GetLatestReading(deviceAddress, valueType); } public DeviceHistory GetDeviceHistory(string deviceAddress) { return WeatherServiceCommon.GetDeviceHistory(deviceAddress); } public Dictionary> GetDeviceHistoryByValueType(WeatherValueType valueType) { return WeatherServiceCommon.GetDeviceHistoryByValueType(valueType); } public Dictionary> GetWindSpeedHistory(int groupIntervalMinutes) { return WeatherServiceCommon.GetWindSpeedHistory(groupIntervalMinutes); } public Dictionary GetWindDirectionHistory() { return WeatherServiceCommon.GetWindDirectionHistory(); } public bool Subscribe() { try { var callback = OperationContext.Current.GetCallbackChannel(); if (!Subscribers.Contains(callback)) Subscribers.Add(callback); return true; } catch { return false; } } public bool Unsubscribe() { try { var callback = OperationContext.Current.GetCallbackChannel(); if (Subscribers.Contains(callback)) Subscribers.Remove(callback); return true; } catch { return false; } } internal static void FireNotification(DeviceBase device) { // Create a list of callbacks that need to be removed var removeList = new List(); // Loop over each subscriber foreach (var callback in Subscribers) { // If the callback connection isn't open... if ((callback as ICommunicationObject).State != CommunicationState.Opened) { // ...add it to the remove list and continue removeList.Add(callback); continue; } try { // Make the callback callback.OnDeviceUpdate(device); } catch { // The callback failed - add it to the remove list removeList.Add(callback); } } // Remove all callbacks in the remove list removeList.ForEach(o => Subscribers.Remove(o)); } } }