繁体中文
设为首页
加入收藏
当前位置:.Net技术首页 >> Asp.Net开发 >> Using the Remoting Callbacks in .Net Applications

Using the Remoting Callbacks in .Net Applications

2007-04-15 08:00:00  作者:  来源:互联网  浏览次数:0  文字大小:【】【】【
简介:Implementation The sample solution of the Remote Callbacks implemenation is divided into several projects: ContractObject - common abstract definitions (see the above) RemoteCallbackLib - RemoteCa...

Implementation

The sample solution of the Remote Callbacks implemenation is divided into several projects:

ContractObject - common abstract definitions (see the above)

RemoteCallbackLib - RemoteCallback Custom Attribute (see the above)

RemoteObjectA - classic .Net object hosted in the HostServer

RemoteObjectX - .Net Service (COM+) hosted in the HostServer

RemoteObjectWS - Web Service hosted in the IIS

HostServer - console server program

RemoteWindowsForm - Windows Form client program

also the solution included the following config files:

HostServer.exe.config - the Remoting config info for objects hosted by HostServer

RemoteWindowsForm.exe.config - the config info for Remoting objects using by this client

RemoteCallbackLib

The following code snippet shows the implementation of the RemoteCallbackAttribute. Its design is based on the Refection of the "parent" assembly, where located all metadata of the Callback object. The RemoteCallbackLib is built into the separate assembly which it can be reused by another remoting clients.

namespace RKiss.RemoteCallbackLib

{

[AttributeUsage(AttributeTargets.Field)]

public class RemoteCallbackAttribute : Attribute

{

private string _desc;

private string _protocol;

private int _port;

public string desc

{

get { return _desc; }

set {_desc = value; }

}

public string protocol

{

get { return _protocol; }

set {_protocol = value; }

}

public int port

{

get { return _port; }

set {_port = value; }

}

public RemoteCallbackAttribute() : this("tcp", 0) {}

public RemoteCallbackAttribute(string sProtocol) : this(sProtocol, 0) {}

public RemoteCallbackAttribute(string sProtocol, int iPort)

{

protocol = sProtocol;

port = iPort;

}

}

// Creating remoting stuff based on the properties of the CallbackAttribute

// Note that all callback class' have to located in the same (parent) assembly!

public class RemoteCallbackSubscriber

{

private Hashtable HT = Hashtable.Synchronized(new Hashtable());

private string site = "localhost";

public RemoteCallbackSubscriber(object parent)

{

Type typeParent = parent.GetType();

foreach(FieldInfo fi in typeParent.GetFields())

{

foreach(Attribute attr in fi.GetCustomAttributes(true))

{

if(attr is RemoteCallbackAttribute)

{

RemoteCallbackAttribute rca = attr as RemoteCallbackAttribute;

// open in/out channel

int port = rca.port;

if(port == 0)

{

Random rdmPort = new Random(~unchecked((int)DateTime.Now.Ticks));

port = rdmPort.Next(1, ushort.MaxValue);

}

// create channel

IChannel channel = null;

if(rca.protocol == "tcp")

channel = new TcpChannel(port);

else

if(rca.protocol == "http")

channel = new HttpChannel(port);

else

throw new Exception(string.Format("The '{0}' is not recognize protocol.", rca.protocol));

// register channel

ChannelServices.RegisterChannel(channel);

// register a Callback Object

string nameofCallbackObject = fi.FieldType.FullName;

Type typeofCallbackObject = typeParent.Assembly.GetType(nameofCallbackObject);

RemotingConfiguration.RegisterWellKnownServiceType(

typeofCallbackObject,

nameofCallbackObject,

WellKnownObjectMode.Singleton);

// create proxy

string urlofCallbackObject = string.Format(@"{0}://{1}:{2}/{3}",

rca.protocol, site, port, nameofCallbackObject);

object proxyCB = Activator.GetObject(typeofCallbackObject, urlofCallbackObject);

fi.SetValue(parent, proxyCB);

//

//store into the HT

HT[fi.Name] = channel;

}

}

}

}

public IChannel this [string nameofCallback]

{

get { return HT[nameofCallback] as IChannel; }

}

}

}

RemoteObject (A , X and WS)

The design pattern of the Remoting methods is the same for any of these remoting objects. The following code snippet shows the RemoteObjectA class derived from the MarshalByRefObject class and IRmObject interface.

using RKiss.RemoteObject; // abstract definitions

namespace RKiss.RemoteObjectA

{

public class RmObjectA : MarshalByRefObject, IRmObject

{

public RmObjectA()

{

Trace.WriteLine(string.Format("[{0}]RmObjectA activated", GetHashCode()));

}

public string Echo(string msg)

{

Trace.WriteLine(string.Format("[{0}]RmObjectA.Echo({1})", GetHashCode(), msg));

return msg;

}

// stateless callbacks

public string GiveMeCallback(int timeinsec, string ticketId, object objwire)

{

RemoteCallback wire = objwire as RemoteCallback;

bool bProgress = true;

CallbackEventArgs cea = new CallbackEventArgs();

cea.TicketId = ticketId;

cea.State = "running ...";

cea.Sender = GetType().ToString();

wire(cea.Sender, cea);

while(timeinsec-- > 0 && bProgress)

{

Thread.Sleep(1000);

cea.State = timeinsec;

bProgress = wire(cea.Sender, cea);

}

cea.State = bProgress?"done":string.Format("aborted at {0}", ++timeinsec);

wire(cea.Sender, cea);

//

Trace.WriteLine(string.Format("[{0}]RmObjectA.GiveMeCallback({1}, {2}, {3})",

GetHashCode(), timeinsec, ticketId, wire.GetType().FullName));

return ticketId;

}

}

}

There are implementation of two methods of the IRmObject interface in the object. The first one - Echo has a test purpose, the other one - GiveMeCallback simulated some time consuming work with notification of the method state using the Remoting Callback mechanism. The method state is wrapped and serialized by the CallbackEventArgs object.

Now I will show you only differencies in the following remote objects:

责任编辑:admin
相关文章