在传统的网络应用编写中都是通过接收消息处理然后应答,但在.net 3.0后提供了一个基于业务接口调用的网络交互体系WCF.基于WCF .NET程序可以通过接口调用的方式进行远程业务调用处理.由于WCF是MS提供的体系,所以在mono和xamarin所支持的其他平台都没有良好地被支持.但随便着mono和xamarin的迅速发展,基于业务接口远程调用的服务体系该提供给更多平台提供通讯的便利性;为了解决这些问题EC组件提供了一套基于业务接口远程调用方法实现,借助于mono和xamarin可以使些功能简单应用到linux,android,wp和ios之上.
通过EC只需要用接口就能描述一个远程通讯操作,其原体系原理类似于WCF;由于是针对mono所支持的功能实现.所以提供了多平台的支持.下面介绍一下如何用EC构建一个多台的远程接口调用功能.
接口定义
在EC中描述服务的接口并不需要定义任何规范,不过由于基础通过是通过protobuf来实现基础RPC通讯,所以对于一些用户自定义的对象需要通过protobuf进行描述.以下是示例接口和对象结构的定义.
public interface IUserService { User Register(string name, string email); void GetRegisteTime(string name, out DateTime time); } [ProtoContract] [EC.MessageID(0x0001)] public class User { [ProtoMember(1)] public string Name { get; set; } [ProtoMember(2)] public string Email { get; set; } [ProtoMember(3)] public DateTime CreateTime { get; set; } }
以上是定义一个简单用户服务接口,包括的功能用注册和获取用户注册时间.EC不紧紧提供普通参数成员的支持,同样也提供对out参数的支持.
服务实现
在前面已经有文章介绍EC如果开启一个网服务,在不需要任何配置的情况即可开启,包括现有介绍的远程接口调用功能.你只需要在实现远程接口的类上打上一个SOAServer标答在EC启的时候就会自动加载并运行.具体代码如下:
[EC.Remoting.SOAService(typeof(IUserService))] class Program:IUserService { static void Main(string[] args) { EC.ECServer.Open(); System.Threading.Thread.Sleep(-1); } public User Register(string name, string email) { Console.WriteLine("register name:{0}\t email:{1}", name, email); User user = new User(); user.Name = name; user.Email = email; user.CreateTime = DateTime.Now; return user; } public void GetRegisteTime(string name, out DateTime time) { time = DateTime.Now; Console.WriteLine("get registe time:{0}", time); } }
以上代码是不是非常简单,只需要实现接口那服务就自然会加载处理.
客户端
EC同时提供简单的功能库来处理接口远程调用,只需要引用接口和自定义的参数类型即可以.并不需要去实现接口来调用.组件会根据接口内部构建一个代理调从而简化客户端调用繁琐性.
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private ProtoClient mChannel = new ProtoClient("127.0.0.1", 10034); private IUserService UserService; private void Form1_Load(object sender, EventArgs e) { UserService = mChannel.CreateInstance<IUserService>(); } private void btnRegister_Click(object sender, EventArgs e) { btnRegister.Text="Register(+" + UserService.Register(txtName.Text,txtEMail.Text).CreateTime+")"; } private void button2_Click(object sender, EventArgs e) { DateTime dt; UserService.GetRegisteTime("test",out dt); button2.Text="GetTime(" + dt+")"; } }
直接构建一个ProtoClient的客户端对象,然后通过客户端对象创建一个代理操作接口即可;对象是不需要关系连接的有效性,接口代理内部会根据连接的情况来确认在调用的时候是否需要便建连接.
Android
EC同样提供xamarin的功能库,不过不象.NET平台那样提供protobuf和msgpack的支持;所以在使用上会有一些差异由于只支持protobuf所以xamarin下提供了ServiceChannel这样一个对象来代码原来的ProtoClient,虽然名称 不一样不过功能还是一致的.
[Activity (Label = "EC.InterfaceProxy", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity { private EC.ServiceChannel mChannel = new ServiceChannel("10.0.2.2",10034); private IUserService UserService; protected override void OnCreate (Bundle bundle) { base.OnCreate (bundle); ServiceChannel.Register (typeof(MainActivity).Assembly); UserService = mChannel.CreateInstance<IUserService> (); // Set our view from the "main" layout resource SetContentView (Resource.Layout.Main); EditText name = this.FindViewById<EditText> (Resource.Id.txtName); EditText email = this.FindViewById<EditText> (Resource.Id.txtEMail); Button register = this.FindViewById<Button> (Resource.Id.cmdRegister); register.Click += delegate { register.Text ="Register(" + UserService.Register(name.Text,email.Text).CreateTime+")"; }; Button gettime = this.FindViewById<Button> (Resource.Id.cmdGetTime); gettime.Click += delegate { DateTime dt; UserService.GetRegisteTime ("test", out dt); gettime.Text = "GETTIME(" + dt + ")"; }; // Get our button from the layout resource, // and attach an event to it } }
整体调用都一样,不过有一个地方需要注意的就是在移动平台下需要调用ServiceChannel.Register功能把用户自定义的消息类型注册到组件中,主要是保证protobuf在RPC处理过程能解决用户的自定义类型.
总结
由于EC基于标准的托管库实现的同时也兼容mono,所以通过EC编写的通讯功能都可以运行在windows和linux之下.如果你有移动平台的需要借助于xamarin可以轻易地应用在android,ios和wp的移动系统之上.