#region License Information /* HeuristicLab * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.ServiceModel; using HeuristicLab.Common; using HeuristicLab.Hive.Tracing; namespace HeuristicLab.Hive.Contracts { public class WcfServicePool { private static object locker = new object(); private string hostAddress; public string HostAddress { get { return hostAddress; } set { if (hostAddress != value) { hostAddress = value; this.factory = null; } } } private string endpointName; private string username; public string Username { get { return username; } set { if(username != value) { username = value; this.factory = null; } } } private string password; public string Password { set { if (password != value) { password = value; this.factory = null; } } } private ChannelFactory factory = null; private Disposable disposableService = null; private int requestCount = 0; public WcfServicePool(string username, string password, string endpointName) { this.username = username; this.password = password; this.endpointName = endpointName; } public WcfServicePool(string hostAddress, string username, string password, string endpointName) : this(username, password, endpointName) { this.hostAddress = hostAddress; } private T CreateFacade(string endpointName) { lock (locker) { try { return CreateChannel(endpointName); } catch (EndpointNotFoundException ex) { OnExceptionOccured(ex); } return default(T); } } protected virtual T CreateChannel(string endpointName) { if (factory == null) { factory = new ChannelFactory(endpointName); if (!string.IsNullOrEmpty(hostAddress)) { WcfSettings.SetEndpointAddress(factory.Endpoint, hostAddress); } factory.Credentials.UserName.UserName = username; factory.Credentials.UserName.Password = password; } return factory.CreateChannel(); } public Disposable GetService() { lock (locker) { requestCount++; Logger.Debug("Request for ServiceProxy (count: " + requestCount + ")"); if (disposableService != null) { if (GetServiceState() == CommunicationState.Faulted) { DisposeService(); } } if (disposableService == null) { disposableService = new Disposable(CreateFacade(this.endpointName)); RegisterServiceEvents(); } return disposableService; } } private void RegisterServiceEvents() { disposableService.OnDisposing += new EventHandler(disposableService_OnDisposing); ((ICommunicationObject)disposableService.Obj).Faulted += new EventHandler(WcfServicePool_Faulted); } private void DeregisterServiceEvents() { disposableService.OnDisposing -= new EventHandler(disposableService_OnDisposing); ((ICommunicationObject)disposableService.Obj).Faulted -= new EventHandler(WcfServicePool_Faulted); } private CommunicationState GetServiceState() { return ((ICommunicationObject)disposableService.Obj).State; } void WcfServicePool_Faulted(object sender, EventArgs e) { OnExceptionOccured(new CommunicationException(e.ToString())); } private void disposableService_OnDisposing(object sender, EventArgs e) { DisposeService(); } public void DisposeService() { lock (locker) { requestCount--; Logger.Debug("Disposing ServiceProxy (count: " + requestCount + ")"); if (requestCount == 0) { try { DeregisterServiceEvents(); WcfSettings.DisposeWcfClient((ICommunicationObject)disposableService.Obj); } catch (Exception e) { OnExceptionOccured(e); } finally { disposableService = null; } } else if (requestCount < 0) { throw new WcfServicePoolException("requestCount cannot be less than 0."); } } } public event EventHandler> ExceptionOccured; private void OnExceptionOccured(Exception e) { lock (locker) { var handler = ExceptionOccured; if (handler != null) handler(this, new EventArgs(e)); } } } }