为了不在客户端放置通用库文件,先定义接口,让通用库继承接口,然后在客户端只使用接口.问题是:在客户端使用通用库时
ClientActivatedType CAObject = new ClientActivatedType();
ILease serverLease = (ILease)RemotingServices.GetLifetimeService(CAObject);
MyClientSponsor sponsor = new MyClientSponsor();
serverLease.Register(sponsor);
是可以通过的,客户端发起租约成功.但,当只引用接口时:
IcskGeneral CAObject ;
CAObject=(IcskGeneral)Activiter.GetObject(TypeOf(IcskGeneral),url);
ILease serverLease = (ILease)RemotingServices.GetLifetimeService(CAObject);
报错:错误 1 与“System.Runtime.Remoting.RemotingServices.GetLifetimeService(System.MarshalByRefObject)”最匹配的重载方法具有一些无效参数
错误2 参数“1”: 无法从“cdling.IcskGeneral”转换为 system.MarshalByRefObject”报错时光标在GetLifetimeService(CAObject)的CAObject 上.在任炅的讲座中只提到过,但在示例中都是引用的通用库,请问大师门如何解决,因为我不想把通用库放到客户端去!
ClientActivatedType CAObject = new ClientActivatedType();
ILease serverLease = (ILease)RemotingServices.GetLifetimeService(CAObject);
MyClientSponsor sponsor = new MyClientSponsor();
serverLease.Register(sponsor);
是可以通过的,客户端发起租约成功.但,当只引用接口时:
IcskGeneral CAObject ;
CAObject=(IcskGeneral)Activiter.GetObject(TypeOf(IcskGeneral),url);
ILease serverLease = (ILease)RemotingServices.GetLifetimeService(CAObject);
报错:错误 1 与“System.Runtime.Remoting.RemotingServices.GetLifetimeService(System.MarshalByRefObject)”最匹配的重载方法具有一些无效参数
错误2 参数“1”: 无法从“cdling.IcskGeneral”转换为 system.MarshalByRefObject”报错时光标在GetLifetimeService(CAObject)的CAObject 上.在任炅的讲座中只提到过,但在示例中都是引用的通用库,请问大师门如何解决,因为我不想把通用库放到客户端去!
CAObject=(IcskGeneral)Activiter.GetObject(TypeOf(IcskGeneral),url);//强行转换一下
System.MarshalByRefObject tmp = (System.MarshalByRefObject)CAObject;ILease serverLease = (ILease)RemotingServices.GetLifetimeService(tmp);
捕获的错误:uri is null.
但是IcskGeneral接口不能转换为ClientActivatedType
server configuration
<configuration>
<system.runtime.remoting>
<application >
<service>
<activated type="cdling.ClientActivatedType, cskGeneral" objectUri="cskGeneral.rem"/>
</service>
<channels>
<channel port="8001" ref="tcp">
<serverProviders>
<formatter ref="soap" typeFilterLevel="Full"/>
<formatter ref="binary" typeFilterLevel="Full"/>
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>client configuration
<configuration>
<system.runtime.remoting>
<application>
<client url="tcp://localhost:8001">
<activated type="cdling.ClientActivatedType, cskGeneral"/>
</client>
<channels>
<channel ref="tcp" port="0">
<serverProviders>
<formatter ref="soap" typeFilterLevel="Full"/>
<formatter ref="binary" typeFilterLevel="Full"/>
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>
而在客户端不作用配置文件就出错了:
// 通过编程设置反序列的级别
BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
provider.TypeFilterLevel = TypeFilterLevel.Full;
// 设置通道属性
IDictionary props = new Hashtable();
props["port"] = 0;
//注册TCP通道,用于连接自己或者他人的服务器。
TcpChannel chn = new TcpChannel(props, null, provider);
ChannelServices.RegisterChannel(chn, false);
IcskGeneral CAObject = (IcskGeneral)Activator.GetObject(typeof(cdling.IcskGeneral), "tcp://localhost:8001/cskGeneral.rem");
Console.WriteLine("Client-activated object: " + CAObject.test("客户端发出的数据!"));运行至此报错:找不到请求的服务.
ClientActivatedType obj = new ClientActivatedType();
ObjRef objref = RemotingServices.Marshal(obj,"ClientActivatedType.rem")
可以解决:找不到请求的服务.的问题,而讲座中没有这样做哇,是为什么呢?
这里错了.
若要在客户端使用接口,就必须是服务端激活模式.否则客户端怎么知道构造函数的签名呢?!
System.MarshalByRefObject tmp = (System.MarshalByRefObject)CAObject;
上面的方式是可以的,我的就是这样用的。
虽然客户端对象表现为接口类型,但从服务端返回的实际对象是继承于System.MarshalByRefObject的。但我也有一个问题
我注册续约者在局域网内可以,但到Internet上就不行了。
服务端方法返回对象与数据包都是可以的,就是传递对象(作为方法参数)到服务端去,就不行了。
有没高手知道原因?