|
using System;
using System.Collections;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using WcfProxyManager.Behaviors;
using WcfProxyManager.Helpers;
namespace WcfProxyManager
{
/// <summary>
/// </summary>
public static class ProxyManager
{
//Our Ubber Brand New Cool cache Objects
private static readonly Hashtable _channelFactoryCache = new Hashtable();
private static readonly Hashtable _proxyCache = new Hashtable();
private static readonly Hashtable _dnsCache = new Hashtable();
// Return an Encapsulated IClientChannel
public static T GetProxy<T>()
{
var t = typeof (T);
if (!_proxyCache.ContainsKey(t))
{
try
{
_proxyCache.Add(t, createProxy<T>());
}
catch (Exception ex)
{
throw new Exception("Failed to create provider: " + ex.Message, ex);
}
}
var s = (ProxyBase<T>) _proxyCache[t];
var ic = (IClientChannel) s.InnerChannel;
//here is the key Abort anything and force dispose
ic.Abort();
// Recreate the channel there is a small amount of overhead here about 4-5 milliseconds
// Well worth the ease of deployment / durability
s.SetChannel();
return s.InnerChannel;
}
/// <summary>
/// This is where we new up an encapsulated IClientChannel
/// </summary>
/// <typeparam name="T"> </typeparam>
/// <returns> </returns>
internal static ProxyBase<T> createProxy<T>()
{
var t = typeof (T);
// Get The Channel Factory or create it if needed
ChannelFactory channelFactory;
lock (_channelFactoryCache)
{
if (_channelFactoryCache.ContainsKey(t))
{
channelFactory = (ChannelFactory) _channelFactoryCache[t];
}
else
{
channelFactory = createChannelFactory<T>();
_channelFactoryCache.Add(t, channelFactory);
}
}
EndpointAddress endpoint = null;
//get Configuration
var s = ConfigurationHelper.GetKey("HOST", Environment.MachineName);
var port = ConfigurationHelper.GetKey("PORT", "8080");
var binding = ConfigurationHelper.GetKey("BINDING", "HTTP");
var serviceName = typeof (T).ToString();
//Ser the correct service name Defaults to the interface name minus the I
if (serviceName[0] == char.Parse("I"))
{
serviceName = serviceName.Remove(0, 1);
}
//Create the URI
string server;
switch (binding)
{
case "TCP":
server = string.Format("net.tcp://" + getIPAddress(s) + ":{0}/{1}", port, serviceName);
endpoint = new EndpointAddress(server);
break;
case "HTTP":
server = string.Format("http://" + getIPAddress(s) + ":{0}/{1}", port, serviceName);
endpoint = new EndpointAddress(server);
break;
}
//Create the Enapsulated IClientChanenel
var pb = new ProxyBase<T>((ChannelFactory<T>) channelFactory, endpoint);
return pb;
}
// For speed I have us resolving to the Ip of the end
// Address. This is probally totally not needed
private static string getIPAddress(string server)
{
lock (_dnsCache)
{
if (!_dnsCache.ContainsKey(server))
{
var host = Dns.GetHostEntry(server);
_dnsCache.Add(server, host.AddressList[0].ToString());
}
return _dnsCache[server].ToString();
}
}
/// <summary>
/// </summary>
/// <typeparam name="T"> </typeparam>
/// <returns> </returns>
/// <exception cref="ArgumentException"></exception>
private static ChannelFactory createChannelFactory<T>()
{
Binding b = null;
switch (ConfigurationHelper.GetKey("BINDING", "HTTP"))
{
case "HTTP":
b = new BasicHttpBinding();
break;
case "TCP":
b = new NetTcpBinding();
break;
}
if (b != null)
{
var factory = new ChannelFactory<T>(b);
// This is super important
// Why ? This is where you can add
// Custom behaviors to your outgoing calls
// like Message Inspectors ... or behaviors.
ApplyContextToChannelFactory(factory);
return factory;
}
return null;
}
/// <summary>
/// </summary>
/// <param name="factory"> </param>
public static void ApplyContextToChannelFactory(ChannelFactory factory)
{
//This area in where custom nehaviors are added
if (factory == null)
{
throw new ArgumentException("The argument 'factory' cannot be null.");
}
// here is an example of a behavior swap were some default
// values where set on the replacement
foreach (var desc in factory.Endpoint.Contract.Operations)
{
desc.Behaviors.Remove<DataContractSerializerOperationBehavior>();
desc.Behaviors.Add(new ReferencePreservingBehavior(desc));
}
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.