在生成远程对象时,创建和初始化新对象就是激活。远程处理系统须始终了解所需的激活类型才能将对象设置为可供客户端使用。激活有两种方式:服务器激活和客户端激活
服务器激活
服务器激活的对象是生存期直接受服务器直接控制的对象。仅当客户端对对象进行方法调用时,服务器应用程序域才会创建这些对象,而不是当客户端调用new或Activator.GetObject的时候。客户端请求服务器激活类型的实例时,会在客户端应用程序域中创建一个代理。服务器激活类型只允许使用默认构造器。如果想使用特定的采用参数的构造器创建实例的类型,可以使用客户端激活,也可以动态发布特定实例。
服务器激活的对象有两种激活模式:Singleton和SingleCall,这两种模式又叫已知对象,由枚举类型:WellKnownObjectMode来标识。
Singleton类型在任一时刻只有一个实例。所有的客户端请求都将由这个实例提供服务。如果不存在实例,则服务器创建一个,且所有的后来的客户端请求都将由这个实例提供服务。对于单件类型,会关联到默认的生存期。
SingleCall类型针对每个客户端请求创建一个实例。下一个方法调用将由其他服务器实例提供服务,即使在系统尚未回收前一个实例的引用的情况下也是这样。
类RemotingConfiguration
方法 RegisterWellKnownServiceType 将服务器上的对象类型注册为已知类型
public static void RegisterWellKnownServiceType(
Type type,
string objectUri,
WellKnownObjectMode mode)
所有知道已注册已知对象的URI的客户都可以获取该对象的代理,方法是:用ChannelServices注册信道,然后调用new或Activator.GetObject方法来激活对象。
·当用new来激活对象时,须先要使用RegisterWellKnownClientType方法在客户端注册该已知对象类型。调用RegisterWellKonwnClientType方法向远程处理基础结构提供远程对象的位置,使new关键字可以创建它。
·当用Activator.GetObject方法来激活已知对象时,须将对象的URL作为参数提供给该方法,所以在这种情况下,不用预先在客户端注册。
当调用到达服务器后,系统从消息中提取URI,检查远程处理表以定位与该URI匹配的对象的引用,然后实例化该对象,将方法调用转发给该对象。如果是SingleCall,则在方法调用完成后,该对象被销毁。为每个方法创建对象的一个新实例。
Activator.GetObject与new的区别是:Activator.GetObject可以指定URL作为参数,new的时候是从配置中获取URL
(1)通过Actovator.GetObject方法来获取代理
Activator类位于System下。它包含一些方法,用于在本地或从远程创建对象类型,或获取对现有远程对象的引用。其中GetObject这个方法有2个重载,方法的意义是:为已知对象或 XML Web services 创建一个代理。
GetObject(Type, String) 为指定类型和 URL 所指示的已知对象创建一个代理。
GetObject(Type, String, Object) 为指定类型、URL 和通道数据所指示的已知对象创建一个代理。
以第一个2个参数的方法为例子:第一个参数Type,是在服务端注册为已知类型的类型,第二个参数是已知对象的URL
服务端:
HttpChannel _channel = new HttpChannel(10001);
ChannelServices.RegisterChannel(_channel,false);
Console.WriteLine("http 通道remoting服务开始……");
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(selfRemoteObject), "selfRemoteObject",
WellKnownObjectMode.Singleton);
客户端:
public void TestService()
{
selfRemoteObject app =
(selfRemoteObject)Activator.GetObject(
typeof(selfRemoteObject),
"http://localhost:10001/selfRemoteObject");
Assert.AreEqual(13,app.Plus(3, 10));
}
(2)通过new来创建代理
当用new来激活对象时,先要使用RegisterWellKnownClientType方法在客户端注册该已知对象类型。然后使new关键字可以创建它。
服务端还是(1)中的服务端
客户端:
public void TestServiceNew()
{
RemotingConfiguration.RegisterWellKnownClientType(
typeof(selfRemoteObject),
"http://localhost:10001/selfRemoteObject");
selfRemoteObject app = new selfRemoteObject();
Assert.AreEqual(13, app.Plus(3, 10));
}
以上两种方法在创建代理后,调用方法时,服务端会管理已知类型对象的创建工作,这种生成对象是按默认的构造器(无参)来进行。
客户端激活
客户端激活的对象由调用应用程序域控制其生存期的对象,这种情况与应用程序域控制本地对象生存期一样。
创建客户端激活对象时,客户端将调用服务器。服务器实例化远程对象,并将对象引用返回给客户端。客户端使用这个引用创建远程对象的代理。每当客户端创建客户端激活对象的实例时,都会收到与远程对象的特定服务器实例进行通信的代理,直至其租约过期,内存被回收为止。
采用客户端激活方式的步骤:
·要在服务器上创建客户端激活的对象的实例,要知道它的Type
·使用RegisterActivatedServiceType方法在服务端注册它。
客户端步骤:
·客户端先向ChannelServices注册一个通道,
·通过调用new或Activator.CreateInstance激活对象。
创建客户端激活类型实例的两种方式:
·以new来进行
·以Activator.CreateInstance的调用中传递远程对象
先准备服务端:
HttpChannel _channel = new HttpChannel(10001);
ChannelServices.RegisterChannel(_channel,false);
Console.WriteLine("http 通道remoting服务开始……");
RemotingConfiguration.ApplicationName = "selfRemoteObject";
RemotingConfiguration.RegisterActivatedServiceType
(typeof(selfRemoteObject));
Console.Read();
服务端要通过RegisterActivatedServiceType方法来注册类型,且先要设定ApplicationName,这个就相当于URL
客户端
(1)以new来进行
public void TestClientNew()
{
HttpChannel _channel = new HttpChannel();
ChannelServices.RegisterChannel(_channel, false);
RemotingConfiguration.RegisterActivatedClientType
(
typeof(selfRemoteObject),
"http://localhost:10001/selfRemoteObject");
selfRemoteObject app1 = new selfRemoteObject();
Assert.AreEqual(10, app1.Plus(1, 9));
}
通过new来激活客户端对象类型,先使用RegisterActivatedClientType方法在客户端注册该对象类型,然后new就可以了。
(2)Activator.CreateInstance
如果用CreateInstance,则要提供远程应用程序的URL作为参数,不用在客户端注册类型。如果要用到URL做参数,则URL要封装在UrlAttribute类实例中。
public void TestClientInstance()
{
HttpChannel _channel = new HttpChannel();
ChannelServices.RegisterChannel(_channel,false);
object[] url={new UrlAttribute
("http://localhost:10001/selfRemoteObject")};
selfRemoteObject app1 =
(selfRemoteObject)Activator
.CreateInstance(typeof(selfRemoteObject), null, url);
Assert.AreEqual(10, app1.Plus(1, 9));
}
客户端激活方式可以使用带参构造器来创建远程对象实例。
修改远程对象,添加一属性一个带参构造器:
public int Unid { get; set; }
public selfRemoteObject() { }
public selfRemoteObject(int iUnid)
{
Unid = iUnid;
}
添加了带参构造器,要显示声明默认的无参构造器。
通过new方法来创建对象实例。
selfRemoteObject app1 = new selfRemoteObject();
Assert.AreEqual(0, app1.Unid);
selfRemoteObject app2 = new selfRemoteObject(10);
Assert.AreEqual(10, app2.Unid);
激活方式,是远程对象实例创建的的管理方式。服务器端激活就是由服务端来管理远程对象的创建,在这种方式下,当客户端调用方法时,才创建实例;客户端激活由客户端来管理远程对象的创建,在这种方式下,当客户端发出调用就创建实例。
RemotingConfiguration类的类型注册方法:
RegisterActivatedClientType 将客户端上的对象 Type 注册为可在服务器上激活的类型。
RegisterActivatedServiceType 将服务端上的对象 Type 注册为可根据请求从客户端激活的类型。
RegisterWellKnownClientType 将客户端上的对象 Type 注册为已知类型(“单个调用”(singlecall) 或 singleton)。
RegisterWellKnownServiceType 将服务端上的对象 Type 注册为已知类型(“单个调用”(singlecall) 或 singleton)。
断开
RemotingServices.Disconnect这个方法用于阻止对象通过注册的远程处理信道再接收消息。它的参数须是实例化的对象(要关闭的),服务端注册类型要通过Marshal方法来进行:
HttpChannel _channel = new HttpChannel(10001);
ChannelServices.RegisterChannel(_channel,false);
Console.WriteLine("http 通道remoting服务开始……");
selfRemoteObject obj=new selfRemoteObject();
RemotingServices.Marshal(obj, "selfRemoteObject");
断开时,通过Disconnect方法:
RemotingServices.Disconnect(obj);