Remoting7调用上下文
调用上下文(CallContext)提供了用于存储属性集的数据槽,可以让我们在调用服务器方法时将一些额外数据一并传送过去。当然,这些额外数据有点限制,就是必须要实现 ILogicalThreadAffinative 接口。调用上下文在应用程序域边界被克隆,其数据槽不在其他逻辑线程上的调用上下文之间共享。
我们利用这个特性写一个简单的身份验证例子。
using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Threading; using System.Security.Permissions; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.CompilerServices; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Lifetime; using System.Runtime.Remoting.Services; namespace Learn.Library.Remoting { public class RemotingTest2 { /// <summary> /// 身份验证类型 /// </summary> [Serializable] public class Identity : ILogicalThreadAffinative { private string username; private string password; public Identity(string username, string password) { this.username = username; this.password = password; } public string Username { get { return username; } set { username = value; } } public string Password { get { return password; } set { password = value; } } } /// <summary> /// 远程类型 /// </summary> public class Data : MarshalByRefObject { public void Test() { // 执行身份验证 Identity identity = CallContext.GetData("identity") as Identity; if (identity != null && identity.Username == "user1" && identity.Password == "pass") { Console.WriteLine("Test AppDomain:{0}", AppDomain.CurrentDomain.FriendlyName); } } } /// <summary> /// 服务器端代码 /// </summary> static void Server() { AppDomain server = AppDomain.CreateDomain("server"); server.DoCallBack(delegate { TcpServerChannel channel = new TcpServerChannel(801); ChannelServices.RegisterChannel(channel, false); RemotingConfiguration.ApplicationName = "test"; RemotingConfiguration.RegisterActivatedServiceType(typeof(Data)); }); } /// <summary> /// 客户端代码 /// </summary> static void Client() { TcpClientChannel channel = new TcpClientChannel(); ChannelServices.RegisterChannel(channel, false); RemotingConfiguration.RegisterActivatedClientType(typeof(Data), "tcp://localhost:801/test"); // 传送身份验证数据 CallContext.SetData("identity", new Identity("user1", "pass")); Data data = new Data(); data.Test(); } static void Main() { Server(); Client(); } } }
数据槽中的数据可以双向传输,也就是说我们可以从服务器返回更多的信息给客户端。
using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Threading; using System.Security.Permissions; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.CompilerServices; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Lifetime; using System.Runtime.Remoting.Services; namespace Learn.Library.Remoting { public class RemotingTest2 { [Serializable] public class ServerTime : ILogicalThreadAffinative { private DateTime time; public ServerTime(DateTime time) { this.time = time; } public DateTime Time { get { return time; } } } /// <summary> /// 远程类型 /// </summary> public class Data : MarshalByRefObject { public void Test() { CallContext.SetData("ExInfo", new ServerTime(DateTime.Now)); Console.WriteLine("Test AppDomain:{0}", AppDomain.CurrentDomain.FriendlyName); } } /// <summary> /// 服务器端代码 /// </summary> static void Server() { AppDomain server = AppDomain.CreateDomain("server"); server.DoCallBack(delegate { TcpServerChannel channel = new TcpServerChannel(801); ChannelServices.RegisterChannel(channel, false); RemotingConfiguration.ApplicationName = "test"; RemotingConfiguration.RegisterActivatedServiceType(typeof(Data)); }); } /// <summary> /// 客户端代码 /// </summary> static void Client() { TcpClientChannel channel = new TcpClientChannel(); ChannelServices.RegisterChannel(channel, false); RemotingConfiguration.RegisterActivatedClientType(typeof(Data), "tcp://localhost:801/test"); Data data = new Data(); data.Test(); Console.WriteLine((CallContext.GetData("ExInfo") as ServerTime).Time); } static void Main() { Server(); Client(); } } }