Asp.net 我是否应该创建ChannelFactory<;T>;在每个需要呼叫服务的网页中?
我有10个网页,都需要调用ICalculatorService和IShoppingCartService的方法,它们都是WCF服务 我有一个ICalculatorService和IShoppingCartService的接口参考 我正在所有网页的PageLoad方法中创建Asp.net 我是否应该创建ChannelFactory<;T>;在每个需要呼叫服务的网页中?,asp.net,wcf,Asp.net,Wcf,我有10个网页,都需要调用ICalculatorService和IShoppingCartService的方法,它们都是WCF服务 我有一个ICalculatorService和IShoppingCartService的接口参考 我正在所有网页的PageLoad方法中创建ChannelFactory和ChannelFactory的实例 但这真的让网页速度变慢了,我不知道这是不是最好的办法 有没有更好的方法来实现这一功能?我建议创建一个简单的IHTTP模块来管理所有频道工厂,这样它们在web应用程
ChannelFactory
和ChannelFactory
的实例
但这真的让网页速度变慢了,我不知道这是不是最好的办法
有没有更好的方法来实现这一功能?我建议创建一个简单的IHTTP模块来管理所有频道工厂,这样它们在web应用程序期间都可以使用,并且可以在所有页面上共享。我不能谈论@Kirk Woll关于4.0的改进,因为我们仍然在使用3.5(我已经为我们的团队推荐了一个升级路径,但还没有得到批准) 我会做两件事,如果它真的是渠道工厂(评论中的一个争论点),或者它是你唯一可以选择(出于你无法控制的原因)来调整性能(我知道Kirk可能会不同意我:):
如果我要使用这两个选项中的任何一个,我会选择选项2。正如最初的评论所指出的,您应该验证ChannelFactory创建确实是性能问题的根源。这绝对是3.5版的问题 这就是我使用的,最初在3.5天内实现。这将缓存ChannelFactory,在ChannelFactory级别处理任何故障,以及管理为每个发送请求创建一个通道并正确关闭通道。下面是这个类的代码 像这样使用它:
var sum = cachedCalculatorService.Send(proxy => proxy.Add(2, 2));
为需要与之通信的每个服务创建一个ServerProxyFactory。将此缓存在您最喜欢的位置以持久化单例(@Tim有一些好的建议)
e、 g
ServerChannelFactory是线程安全的,因此您可以在任意多个线程中重用它
希望这有帮助
代码如下:
namespace WcfHelper
{
using System;
using System.Diagnostics.CodeAnalysis;
using System.ServiceModel;
using Microsoft.Commerce.Marketplace.Common.Util;
/// <summary>
/// A WCF Proxy Factory suitable for server to server web service calls. A new channel will be created for all service communication.
///
/// All sends handle disposing of the Proxy channel properly. If the Proxy is requested directly, the caller is responsible for properly
/// closing/disposing it.
/// </summary>
public class ServerProxyFactory<TContract> : IDisposable where TContract : class
{
private readonly object syncObject = new object();
public ServerProxyFactory(string endpointConfigurationName)
{
endpointConfigurationName.EnsureArgNotNullOrEmpty("endPointConfigurationName");
this.endPointConfigurationName = endpointConfigurationName;
}
private readonly string endPointConfigurationName;
private ChannelFactory<TContract> channelFactory;
protected ChannelFactory<TContract> ChannelFactory
{
get { return this.channelFactory; }
set
{
ChannelFactory<TContract> oldFactory;
lock (this.syncObject)
{
oldFactory = this.channelFactory;
if (oldFactory != null)
{
oldFactory.Faulted -= this.ChannelFactory_Faulted;
}
var newChannelFactory = value;
if (newChannelFactory != null)
{
newChannelFactory.Faulted += this.ChannelFactory_Faulted;
}
this.channelFactory = newChannelFactory;
}
if (oldFactory != null)
{
try
{
((IDisposable)oldFactory).Dispose();
}
catch (CommunicationException)
{
oldFactory.Abort();
}
catch (TimeoutException)
{
oldFactory.Abort();
}
catch (Exception)
{
oldFactory.Abort();
throw;
}
}
}
}
protected TContract Proxy
{
get
{
if (this.disposed)
{
throw new InvalidOperationException(
"A new Proxy was requested after the ServerProxyFactory has been disposed.");
}
if (this.ChannelFactory == null)
{
this.ChannelFactory = new ChannelFactory<TContract>(this.endPointConfigurationName);
}
return this.ChannelFactory.CreateChannel();
}
}
/// <summary>
/// Perform a WCF call specified by serviceCall delegate
/// </summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="serviceCallDelegate"></param>
/// <returns>return value returned by the WCF call</returns>
[SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
public virtual TResult Send<TResult>(Func<TContract, TResult> serviceCallDelegate)
{
TResult result;
TContract proxy = this.Proxy;
try
{
result = serviceCallDelegate(proxy);
}
finally
{
try
{
((IDisposable)proxy).Dispose();
}
catch (CommunicationException)
{
((ICommunicationObject)proxy).Abort();
}
catch (TimeoutException)
{
((ICommunicationObject)proxy).Abort();
}
catch (Exception)
{
((ICommunicationObject)proxy).Abort();
throw;
}
}
return result;
}
/// <summary>
/// Perform a WCF call specified by serviceCall delegate
/// </summary>
/// <param name="serviceCallDelegate"></param>
[SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
public virtual void Send(Action<TContract> serviceCallDelegate)
{
TContract proxy = this.Proxy;
try
{
serviceCallDelegate(proxy);
}
finally
{
if (proxy != null)
{
try
{
((IDisposable)proxy).Dispose();
}
catch (CommunicationException)
{
((ICommunicationObject)proxy).Abort();
}
catch (TimeoutException)
{
((ICommunicationObject)proxy).Abort();
}
catch (Exception)
{
((ICommunicationObject)proxy).Abort();
throw;
}
}
}
}
private void ChannelFactory_Faulted(object sender, EventArgs e)
{
var factory = (ICommunicationObject)sender;
if (factory == this.ChannelFactory)
{
this.ChannelFactory = null;
}
}
#region IDisposable Members
// Track whether Dispose has been called.
private bool disposed;
// Implement IDisposable.
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
this.ChannelFactory = null;
}
this.disposed = true;
}
#endregion
}
}
名称空间WcfHelper
{
使用制度;
使用System.Diagnostics.CodeAnalysis;
使用System.ServiceModel;
使用Microsoft.Commerce.Marketplace.Common.Util;
///
///适用于服务器到服务器web服务调用的WCF代理工厂。将为所有服务通信创建一个新通道。
///
///所有发送正确处理代理通道。如果直接请求代理,则调用方负责正确处理
///关闭/处理它。
///
公共类ServerProxyFactory:IDisposable,其中TContract:class
{
私有只读对象syncObject=新对象();
公共服务器ProxyFactory(字符串endpointConfigurationName)
{
endpointConfigurationName.EnsureArgNotNullOrEmpty(“endpointConfigurationName”);
this.endPointConfigurationName=endPointConfigurationName;
}
私有只读字符串endPointConfigurationName;
私营渠道工厂;
保护通道工厂通道工厂
{
获取{返回this.channelFactory;}
设置
{
渠道工厂老厂;
锁定(此.syncObject)
{
oldFactory=this.channelFactory;
如果(旧工厂!=null)
{
oldFactory.Faulted-=this.ChannelFactory\u Faulted;
}
var newChannelFactory=值;
if(newChannelFactory!=null)
{
newChannelFactory.Faulted+=this.ChannelFactory\u Faulted;
}
this.channelFactory=newChannelFactory;
}
如果(旧工厂!=null)
{
尝试
{
((IDisposable)oldFactory).Dispose();
}
捕获(通信异常)
{
oldFactory.Abort();
}
捕获(超时异常)
{
oldFactory.Abort();
}
捕获(例外)
{
oldFactory.Abort();
投掷;
}
}
}
}
受保护的TContract代理
{
得到
{
如果(本文件已处理)
{
抛出新的InvalidOperationException(
“在处置ServerProxyFactory后请求了新代理。”);
}
if(this.ChannelFactory==null)
{
this.ChannelFactory=新的ChannelFactory(this.endPointConfigurationName);
}
返回此.ChannelFactory.CreateChannel();
}
}
///
///执行serviceCall委托指定的WCF调用
///
///
///
///WCF调用返回的返回值
[SuppressMessage(“Microsoft.Performance”、“CA1800:DonotCast不必要”)]
公共虚拟树结果发送(Func serviceCallDelegate)
{
结果结果;
t合同代理=此.proxy;
尝试
namespace WcfHelper
{
using System;
using System.Diagnostics.CodeAnalysis;
using System.ServiceModel;
using Microsoft.Commerce.Marketplace.Common.Util;
/// <summary>
/// A WCF Proxy Factory suitable for server to server web service calls. A new channel will be created for all service communication.
///
/// All sends handle disposing of the Proxy channel properly. If the Proxy is requested directly, the caller is responsible for properly
/// closing/disposing it.
/// </summary>
public class ServerProxyFactory<TContract> : IDisposable where TContract : class
{
private readonly object syncObject = new object();
public ServerProxyFactory(string endpointConfigurationName)
{
endpointConfigurationName.EnsureArgNotNullOrEmpty("endPointConfigurationName");
this.endPointConfigurationName = endpointConfigurationName;
}
private readonly string endPointConfigurationName;
private ChannelFactory<TContract> channelFactory;
protected ChannelFactory<TContract> ChannelFactory
{
get { return this.channelFactory; }
set
{
ChannelFactory<TContract> oldFactory;
lock (this.syncObject)
{
oldFactory = this.channelFactory;
if (oldFactory != null)
{
oldFactory.Faulted -= this.ChannelFactory_Faulted;
}
var newChannelFactory = value;
if (newChannelFactory != null)
{
newChannelFactory.Faulted += this.ChannelFactory_Faulted;
}
this.channelFactory = newChannelFactory;
}
if (oldFactory != null)
{
try
{
((IDisposable)oldFactory).Dispose();
}
catch (CommunicationException)
{
oldFactory.Abort();
}
catch (TimeoutException)
{
oldFactory.Abort();
}
catch (Exception)
{
oldFactory.Abort();
throw;
}
}
}
}
protected TContract Proxy
{
get
{
if (this.disposed)
{
throw new InvalidOperationException(
"A new Proxy was requested after the ServerProxyFactory has been disposed.");
}
if (this.ChannelFactory == null)
{
this.ChannelFactory = new ChannelFactory<TContract>(this.endPointConfigurationName);
}
return this.ChannelFactory.CreateChannel();
}
}
/// <summary>
/// Perform a WCF call specified by serviceCall delegate
/// </summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="serviceCallDelegate"></param>
/// <returns>return value returned by the WCF call</returns>
[SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
public virtual TResult Send<TResult>(Func<TContract, TResult> serviceCallDelegate)
{
TResult result;
TContract proxy = this.Proxy;
try
{
result = serviceCallDelegate(proxy);
}
finally
{
try
{
((IDisposable)proxy).Dispose();
}
catch (CommunicationException)
{
((ICommunicationObject)proxy).Abort();
}
catch (TimeoutException)
{
((ICommunicationObject)proxy).Abort();
}
catch (Exception)
{
((ICommunicationObject)proxy).Abort();
throw;
}
}
return result;
}
/// <summary>
/// Perform a WCF call specified by serviceCall delegate
/// </summary>
/// <param name="serviceCallDelegate"></param>
[SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
public virtual void Send(Action<TContract> serviceCallDelegate)
{
TContract proxy = this.Proxy;
try
{
serviceCallDelegate(proxy);
}
finally
{
if (proxy != null)
{
try
{
((IDisposable)proxy).Dispose();
}
catch (CommunicationException)
{
((ICommunicationObject)proxy).Abort();
}
catch (TimeoutException)
{
((ICommunicationObject)proxy).Abort();
}
catch (Exception)
{
((ICommunicationObject)proxy).Abort();
throw;
}
}
}
}
private void ChannelFactory_Faulted(object sender, EventArgs e)
{
var factory = (ICommunicationObject)sender;
if (factory == this.ChannelFactory)
{
this.ChannelFactory = null;
}
}
#region IDisposable Members
// Track whether Dispose has been called.
private bool disposed;
// Implement IDisposable.
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
this.ChannelFactory = null;
}
this.disposed = true;
}
#endregion
}
}