标签:
在创建一个服务端的时候都会依托于ServiceHost对象,里面存在一个SingletonInstance指向一个服务实例。而ServiceHost最终都是寄在InstanceContext中。对于单调模式,客户端的每次调用服务端都会创建一个全新的上下文和服务实例。

为了验证上述流程,写了下面这个例子。ServiceBehavior中的InstanceContextMode可以设置服务类型的上下文模式,公三种PerCall、PerSession、Single分别对应单调、回话、单例。这里设置为PerCall。
服务端用了一个Timer定时器,每隔100ms调用GC回收一次垃圾数据。Calculator中定义了构造函数和析构函数,方便看清服务端服务实例的声明周期。
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Timer T = new Timer(s => GC.Collect(), null, 0, 100);
ServiceHost host = new ServiceHost(typeof(Calculator));
host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://localhost:4216");
host.Opened += delegate { Console.WriteLine("Service Start!"); };
host.Open();
Console.Read();
}
}
[ServiceContract]
public interface ICalculator
{
[OperationContract]
int Add(int x, int y);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class Calculator : ICalculator,IDisposable
{
public Calcilator()
{
Console.WriteLine("构造函数Calculator");
}
public int Add(int x, int y)
{
return x + y;
}
~Calcilator()
{
Console.WriteLine("析构函数Calculator");
}
public void Dispose()
{
Console.WriteLine("Dispose方法");
}
}
}
客户端调用:
static void Main(string[] args)
{
ICalculator channel = ChannelFactory<ICalculator>.CreateChannel(new WSHttpBinding(), new EndpointAddress("http://localhost:4216"));
channel.Add(1, 2);
channel.Add(3, 4);
}
输出:

可以看到,对于客户端的每次调用,都是新建了服务实例。
也可以自定义Attribute实现。IInstanceContextProvider是上下文提供者,GetExistingInstanceContext方法获取当前上下文实例,如果当前没有实例则会创建一个新的上下文。这里返回null,让它创建新的上下文。IsIdle方法返回true,意味着这个上下文实例是空闲的,GC可以回收。InitializeInstanceContext和NotifyIdle不实现。
public class PerCallServiceProvider : IInstanceContextProvider
{
public InstanceContext GetExistingInstanceContext(Message message, IContextChannel channel)
{
return null;
}
public void InitializeInstanceContext(InstanceContext instanceContext, Message message, IContextChannel channel)
{}
public bool IsIdle(InstanceContext instanceContext)
{
return true;
}
public void NotifyIdle(InstanceContextIdleCallback callback, InstanceContext instanceContext)
{
}
}
接下来将对每个终结点分发器都创建一个新的InstanceContextProvider。
public class PerCallAttribute : Attribute, IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher channel in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher endpoint in channel.Endpoints)
{
endpoint.DispatchRuntime.InstanceContextProvider = new PerCallServiceProvider();
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{}
}
服务端使用如下,也能实现单调的效果。
[PerCall]
public class Calcilator : ICalculator,IDisposable
{.....}
标签:
原文地址:http://www.cnblogs.com/lh218/p/4532178.html