Host Application Section:
Class Client
{
/// <Summary>
/// Main entry point of the application.
/// </Summary>
[Stathread]
Static void main (string [] ARGs)
{
/* Service request and offline hosting request, tested */
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 = "device account Synchronization Service ";
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 ("device account Synchronization Service proxy", reqmsg. tostring ());
If (result! = NULL)
{
Insxmlmessage retmsg = new insxmlmessage (string) result );
// Debug the output
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)
{
// Delegate the returned message to the corresponding operation
Retmsg. type = insmessagetype. Synchronize;
Continueat (retmsg );
}
Else if (retmsg. State = insmessagestate. networkerror)
{
// Assign a network fault request to the request Manager
Servicerequestmanager. Singleton (). Takeover ("device account Synchronization Service proxy", retmsg, new servicerequestcontinueat (continueat ));
}
}
Console. Read ();
/*
* Service initialization and running instance code, tested
Servicerequestmanager. Singleton (). initialize ();
Servicerequestmanager. Singleton (). submitallsuspend ();
Console. Read ();
*/
}
/// <Summary>
/// The service request returns subsequent operations
/// </Summary>
/// <Param name = "retmsg"> </param>
Public static void continueat (insxmlmessage retmsg)
{
Console. writeline ("continueat called .");
Ioperation operation = operationcontextmanager. Singleton (). createoperation ();
// Operation. Invoke ("synchronization of device accounts to local operations", retmsg );
}
Offline request Manager:
/// <Summary>
/// The entrance delegate after the service request is restored
/// </Summary>
Public Delegate void servicerequestcontinueat (insxmlmessage retmsg );
/// <Summary>
/// Service request Manager
/// </Summary>
Public class servicerequestmanager
{
/// <Summary>
/// Service container
/// </Summary>
Protected iserviceprovider _ context;
/// <Summary>
/// Local proxy
/// </Summary>
Protected idelegate _ service;
/// <Summary>
/// Persistent Service
/// </Summary>
Protected ipersistenceservice _ persistence;
/// <Summary>
/// Wait Interval
/// </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>
/// Cache
/// </Summary>
Protected static hashtable _ cache;
/// <Summary>
/// Single Piece
/// </Summary>
/// <Returns> </returns>
Public static servicerequestmanager Singleton ()
{
If (_ instance = NULL) _ instance = new servicerequestmanager ();
Return _ instance;
}
/// <Summary>
/// Add Cache
/// </Summary>
/// <Param name = "guid"> </param>
/// <Param name = "request"> </param>
Protected void add (system. guid, servicerequest request)
{
_ Cache [guid] = request;
}
/// <Summary>
/// Get from Cache
/// </Summary>
/// <Param name = "guid"> </param>
/// <Returns> </returns>
Protected servicerequest get (system. guid)
{
Object Request = _ cache [guid];
Return request = NULL? Null: request as servicerequest;
}
/// <Summary>
/// Remove from Cache
/// </Summary>
/// <Param name = "guid"> </param>
Protected void remove (system. guid)
{
// Remove from memory
_ Cache. Remove (guid );
// Remove from storage
Iserviceprovider context = clientcontextmanager. Singleton (). createservicecontext ();
Ipersistenceservice Persistence = (ipersistenceservice) Context. getservice (typeof (ipersistenceservice ));
Persistence. Remove (guid );
}
/// <Summary>
/// Take over failed requests
/// </Summary>
/// <Param name = "target"> </param>
/// <Param name = "MSG"> </param>
/// <Param name = "continueat"> </param>
Public void takeover (string target, insxmlmessage MSG, servicerequestcontinueat continueat)
{
// Delegate visibility Verification
If (! Continueat. method. ispublic) throw new argumentexception ("the access scope of the delegate method must be public ");
// Serialize immediately and add cache copies
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>
/// Submit all requests for taking over, triggered by the timer clock
/// </Summary>
Public void submitallsuspend ()
{
Iserviceprovider context = clientcontextmanager. Singleton (). createservicecontext ();
Idelegate service = clientcontextmanager. Singleton (). createdelegate ();
// Create a copy to remove the successfully requested items in the cache during Traversal
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)
{
// Pass the returned message to the registered delegate
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 the receiver
Remove (New GUID (key. tostring ()));
}
}
// Wait for 1 minute until the previous operation is completed.
System. Threading. thread. currentthread. Join (New timespan (_ ticks ));
}
}
/// <Summary>
/// Initialization, called at application startup
/// </Summary>
Public void initialize ()
{
// Load all serialized requests to the memory
Iserviceprovider context = clientcontextmanager. Singleton (). createservicecontext ();
Ipersistenceservice Persistence = (ipersistenceservice) Context. getservice (typeof (ipersistenceservice ));
System. guid [] requests = persistence. possess ();
Foreach (guid in requests)
{
Servicerequest request = retrieverequest (persistence. Activating (guid ));
Add (guid, request );
}
}
/// <Summary>
/// Serialization
/// </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>
/// Deserialization
/// </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 = type. GetType (continueattype). getmethod (continueatmethod );
Return new servicerequest (service, new insxmlmessage (MSG), methodinfo );
}
}