宿主应用程序部分:
class Client
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
/*服务请求及离线托管请求,已测试完毕*/
IServiceProvider context = ClientContextManager.Singleton().CreateServiceContext();
IDelegate service = ClientContextManager.Singleton().CreateDelegate();
System.Collections.Specialized.StringDictionary attributes = new System.Collections.Specialized.StringDictionary();;
InsXMLMessage reqMsg = new InsXMLMessage();
reqMsg.Code = string.Empty;
reqMsg.Command = new InsXMLCommand();
reqMsg.Command.Name = "设备台帐同步服务";
reqMsg.Command.Version = InsMessage.PrepareVersion(System.DateTime.Now);
reqMsg.Command.Data = string.Empty;
reqMsg.Sender = "INS_APP_0001";
reqMsg.Time = System.DateTime.Now;
string debug = reqMsg.ToString();
object result = service.Invoke("设备台帐同步服务代理",reqMsg.ToString());
if(result != null)
{
InsXMLMessage retMsg = new InsXMLMessage((string)result);
//调试输出
Console.WriteLine(Enum.GetName(typeof(InsMessageState),retMsg.State));
Console.WriteLine(Enum.GetName(typeof(InsMessageType),retMsg.Type));
Console.WriteLine(retMsg.Code);
Console.WriteLine(retMsg.Sender);
Console.WriteLine(retMsg.Time.ToString());
Console.WriteLine(retMsg.Command.Name);
Console.WriteLine(retMsg.Command.Version);
Console.WriteLine(retMsg.Command.Data);
if(retMsg.State == InsMessageState.Succeed)
{
//将返回的消息委派到对应操作
retMsg.Type = InsMessageType.Synchronize;
ContinueAt(retMsg);
}
else if(retMsg.State == InsMessageState.NetworkError)
{
//将发生网络故障的请求分派给请求管理器接管
ServiceRequestManager.Singleton().TakeOver("设备台帐同步服务代理",retMsg,new ServiceRequestContinueAt(ContinueAt));
}
}
Console.Read();
/*
* 服务初始化及运行实例代码,已测试完毕
ServiceRequestManager.Singleton().Initialize();
ServiceRequestManager.Singleton().SubmitAllSuspend();
Console.Read();
*/
}
/// <summary>
/// 服务请求返回后续操作
/// </summary>
/// <param name="retMsg"></param>
public static void ContinueAt(InsXMLMessage retMsg)
{
Console.WriteLine("ContinueAt called.");
IOperation operation = OperationContextManager.Singleton().CreateOperation();
//operation.Invoke("设备台帐同步本地操作",retMsg);
}
离线请求管理器部分:
/// <summary>
/// 服务请求恢复后的入口委托
/// </summary>
public delegate void ServiceRequestContinueAt(InsXMLMessage retMsg);
/// <summary>
/// 服务请求管理器
/// </summary>
public class ServiceRequestManager
{
/// <summary>
/// 服务容器
/// </summary>
protected IServiceProvider _context;
/// <summary>
/// 本地代理
/// </summary>
protected IDelegate _service;
/// <summary>
/// 持久服务
/// </summary>
protected IPersistenceService _persistence;
/// <summary>
/// 等待间隔
/// </summary>
protected long _ticks;
private ServiceRequestManager()
{
_cache = Hashtable.Synchronized(new Hashtable());
_context = ClientContextManager.Singleton().CreateServiceContext();
_service = ClientContextManager.Singleton().CreateDelegate();
_persistence = (IPersistenceService)_context.GetService(typeof(IPersistenceService));
_ticks = 60 * 10000000;
}
protected static ServiceRequestManager _instance;
/// <summary>
/// 缓存
/// </summary>
protected static Hashtable _cache;
/// <summary>
/// 单件
/// </summary>
/// <returns></returns>
public static ServiceRequestManager Singleton()
{
if(_instance == null)_instance = new ServiceRequestManager();
return _instance;
}
/// <summary>
/// 加入缓存
/// </summary>
/// <param name="guid"></param>
/// <param name="request"></param>
protected void Add(System.Guid guid,ServiceRequest request)
{
_cache[guid] = request;
}
/// <summary>
/// 从缓存中获取
/// </summary>
/// <param name="guid"></param>
/// <returns></returns>
protected ServiceRequest Get(System.Guid guid)
{
object request = _cache[guid];
return request == null?null:request as ServiceRequest;
}
/// <summary>
/// 从缓存中移除
/// </summary>
/// <param name="guid"></param>
protected void Remove(System.Guid guid)
{
//从内存移除
_cache.Remove(guid);
//从存储移除
IServiceProvider context = ClientContextManager.Singleton().CreateServiceContext();
IPersistenceService persistence = (IPersistenceService)context.GetService(typeof(IPersistenceService));
persistence.Remove(guid);
}
/// <summary>
/// 接管失败的请求
/// </summary>
/// <param name="target"></param>
/// <param name="msg"></param>
/// <param name="continueAt"></param>
public void TakeOver(string target,InsXMLMessage msg,ServiceRequestContinueAt continueAt)
{
//委托可见性校验
if(!continueAt.Method.IsPublic)throw new ArgumentException("委托指向的方法访问范围必须是public");
//立即序列化,并加入缓存副本
IServiceProvider context = ClientContextManager.Singleton().CreateServiceContext();
IPersistenceService persistence = (IPersistenceService)context.GetService(typeof(IPersistenceService));
ServiceRequest request = new ServiceRequest(target,msg,continueAt);
string xml = SerializeRequest(request);
System.Guid instance = persistence.Passivate(xml);
Add(instance,request);
}
/// <summary>
/// 提交所有接管的请求,由定时时钟触发
/// </summary>
public void SubmitAllSuspend()
{
IServiceProvider context = ClientContextManager.Singleton().CreateServiceContext();
IDelegate service = ClientContextManager.Singleton().CreateDelegate();
//创建副本,在遍历过程中移除缓存中请求成功的项目
Hashtable copy = new Hashtable(_cache);
foreach(object key in copy.Keys)
{
ServiceRequest request = Get(new Guid(key.ToString())) as ServiceRequest;
InsXMLMessage reqMsg = request.Message;
object result = service.Invoke(request.Service,reqMsg.ToString());
if(result != null)
{
InsXMLMessage retMsg = new InsXMLMessage((string)result);
if(retMsg.State == InsMessageState.Succeed)
{
//将返回的消息转嫁到注册的委托
if(request.ContinueAtMethod.IsStatic)
{
request.ContinueAtMethod.Invoke(null,new object[]{retMsg});
}
else
{
object instance = request.ContinueAtMethod.DeclaringType.Assembly.CreateInstance(request.ContinueAtMethod.DeclaringType.FullName);
request.ContinueAtMethod.Invoke(instance,new object[]{retMsg});
}
//移除接管
Remove(new Guid(key.ToString()));
}
}
//挂起1分钟以等待上一操作完成
System.Threading.Thread.CurrentThread.Join(new TimeSpan(_ticks));
}
}
/// <summary>
/// 初始化,在应用程序启动时调用
/// </summary>
public void Initialize()
{
//将所有序列化的请求载入内存
IServiceProvider context = ClientContextManager.Singleton().CreateServiceContext();
IPersistenceService persistence = (IPersistenceService)context.GetService(typeof(IPersistenceService));
System.Guid[] requests = persistence.Possess();
foreach(Guid guid in requests)
{
ServiceRequest request = RetrieveRequest(persistence.Activating(guid));
Add(guid,request);
}
}
/// <summary>
/// 序列化
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
protected string SerializeRequest(ServiceRequest request)
{
System.Xml.XmlDataDocument doc = new XmlDataDocument();
XmlDeclaration declaration = doc.CreateXmlDeclaration("1.0","utf-8",string.Empty);
doc.AppendChild(declaration);
XmlNode serviceRequest = doc.CreateNode(XmlNodeType.Element,"ServiceRequest",string.Empty);
XmlAttribute service = doc.CreateAttribute("service");
service.Value = request.Service;
XmlAttribute date = doc.CreateAttribute("date");
date.Value = System.DateTime.Now.ToLongDateString();
XmlAttribute time = doc.CreateAttribute("time");
time.Value = System.DateTime.Now.ToLongTimeString();
serviceRequest.Attributes.Append(service);
serviceRequest.Attributes.Append(date);
serviceRequest.Attributes.Append(time);
XmlNode insMsg = doc.CreateNode(XmlNodeType.CDATA,"InsMessage",string.Empty);
insMsg.Value = request.Message.ToString();
serviceRequest.AppendChild(insMsg);
XmlNode continueAt = doc.CreateNode(XmlNodeType.Element,"ContinueAt",string.Empty);
XmlAttribute type = doc.CreateAttribute("type");
type.Value = request.ContinueAt.Method.DeclaringType.AssemblyQualifiedName;
continueAt.Attributes.Append(type);
XmlAttribute method = doc.CreateAttribute("method");
method.Value = request.ContinueAt.Method.Name;
continueAt.Attributes.Append(method);
serviceRequest.AppendChild(continueAt);
doc.AppendChild(serviceRequest);
return doc.InnerXml;
}
/// <summary>
/// 反序列化
/// </summary>
/// <param name="xml"></param>
/// <returns></returns>
protected ServiceRequest RetrieveRequest(string xml)
{
System.Xml.XmlDataDocument doc = new System.Xml.XmlDataDocument();
doc.LoadXml(xml);
string service = doc.DocumentElement.Attributes["service"].Value;
string msg = doc.DocumentElement.InnerText;
string continueAtType = doc.DocumentElement.SelectSingleNode("ContinueAt").Attributes["type"].Value;
string continueAtMethod = doc.DocumentElement.SelectSingleNode("ContinueAt").Attributes["method"].Value;
MethodInfo methodInfo = Type.GetType(continueAtType).GetMethod(continueAtMethod);
return new ServiceRequest(service,new InsXMLMessage(msg),methodInfo);
}
}