通道工厂和缓存
WCF 客户端应用程序使用 ChannelFactory<TChannel> 类来创建 WCF 服务的通信通道。 创建 ChannelFactory<TChannel> 实例会带来一定的开销,因为这涉及以下操作:
构造 ContractDescription 树
反映所有所需的 CLR 类型
构造通道堆栈
资源的释放
为了尽量减少这种开销,WCF 可以缓存使用 WCF 客户端代理时的通道工厂。
提示
当直接使用 ChannelFactory<TChannel> 类时,您可以直接控制通道工厂创建。
使用 ServiceModel 元数据实用工具 (Svcutil.exe) 生成的 WCF 客户端代理派生自 ClientBase<TChannel>。 ClientBase<TChannel> 定义一个静态 CacheSetting 属性,该属性定义通道工厂缓存行为。 为特定类型设定缓存设置。 例如,将 ClientBase<ITest>.CacheSettings
设置为下面定义的一个值,将只会影响类型为 ITest
的那些代理/ClientBase。 特定 ClientBase<TChannel> 的缓存设置在创建第一个代理/ClientBase 实例后就不可改变。
指定缓存行为
缓存行为通过将 CacheSetting 属性设置为下列值之一指定。
缓存设置值 | 说明 |
---|---|
AlwaysOn | 应用程序域内的 ClientBase<TChannel> 的所有实例都可以参与缓存。 开发人员已经确定对缓存没有不利的安全性影响。 缓存不会关闭,即使访问了 ClientBase<TChannel> 上的“安全性敏感”属性。 ClientBase<TChannel> 的“安全性敏感”属性为 ClientCredentials、Endpoint 和 ChannelFactory。 |
Default | 只有从在配置文件中定义的终结点创建的 ClientBase<TChannel> 的实例才参与应用程序域内的缓存。 以编程方式在应用程序域内创建的 ClientBase<TChannel> 的任何实例都将不参与缓存。 此外,只要访问 ClientBase<TChannel> 的实例的任何“安全性敏感”属性,就将为其禁用缓存。 |
AlwaysOff | 在相关应用程序域内,已对特定类型的 ClientBase<TChannel> 的所有实例关闭缓存。 |
下面的代码段演示如何使用 CacheSetting 属性。
class Program
{
static void Main(string[] args)
{
ClientBase<ITest>.CacheSettings = CacheSettings.AlwaysOn;
foreach (string msg in messages)
{
using (TestClient proxy = new TestClient (new BasicHttpBinding(), new EndpointAddress(address)))
{
// ...
proxy.Test(msg);
// ...
}
}
}
}
// Generated by SvcUtil.exe
public partial class TestClient : System.ServiceModel.ClientBase, ITest { }
在上述代码中,TestClient
的所有实例都将使用相同的通道工厂。
class Program
{
static void Main(string[] args)
{
ClientBase<ITest>.CacheSettings = CacheSettings.Default;
int i = 1;
foreach (string msg in messages)
{
using (TestClient proxy = new TestClient ("MyEndpoint", new EndpointAddress(address)))
{
if (i == 4)
{
ServiceEndpoint endpoint = proxy.Endpoint;
... // use endpoint in some way
}
proxy.Test(msg);
}
i++;
}
}
// Generated by SvcUtil.exe
public partial class TestClient : System.ServiceModel.ClientBase, ITest {}
在上述示例中,TestClient
的所有实例都将使用相同的通道工厂,实例 #4 除外。 实例 # 4 将使用专门供其使用而创建的通道工厂。 此设置适用于此类方案:特定终结点需要的安全设置不同于属于相同通道工厂类型(在此情况下为 ITest
)的其他终结点。
class Program
{
static void Main(string[] args)
{
ClientBase<ITest>.CacheSettings = CacheSettings.AlwaysOff;
foreach (string msg in messages)
{
using (TestClient proxy = new TestClient ("MyEndpoint", new EndpointAddress(address)))
{
proxy.Test(msg);
}
}
}
}
// Generated by SvcUtil.exe
public partial class TestClient : System.ServiceModel.ClientBase, ITest {}
在上面的示例中,TestClient
的所有实例将使用不同的通道工厂。 当每个终结点具有不同的安全需求并且对缓存没有意义时,这非常有用。