#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));
}
}
}
}