来个索引
SilverLight企业应用框架设计【四】实体层设计+为客户端动态生成服务代理(自己实现RiaService)
在上一节中讲到的自动生成的服务代理类核心代码,如下
public event ServiceEventHandler Completed;
public void GetAllMenu()
{
var si = new ServiceInvoker();
si.Completed += new ServiceEventHandler(si_Completed);
si.PrepareInvoke("MenuService", "GetAllMenu", typeof(List<MenuM>));
si.InvokeService();
}
void si_Completed(object sender, ServiceEventArgs e)
{
Completed(sender, e);
}
大家注意到我们是通过ServiceInvoker来调用服务的
实例化ServiceInvoker类之后就注册了ServiceEventHandler事件
此事件是服务调用完成后触发的事件(silverlight 原生的ria service也有一个completed事件)
该事件相关代码如下
public class ServiceEventArgs : EventArgs
{
//服务方法的返回值
public object Result { get; set; }
}
public delegate void ServiceEventHandler(object sender, ServiceEventArgs e);
在si.PrepareInvoke把需要调用的服务类名,方法名,返回值类型(如果有参数,这里还会自动加入参数)
PrepareInvoke方法如下
public void PrepareInvoke(string ClassName,string MethodName,Type ResultType,params object[] objs)
{
className = ClassName;
methodName = MethodName;
resultType = ResultType;
MemoryStream ms = new MemoryStream();
var sb = new StringBuilder();
for(int i=0;i<objs.Length;i++)
{
var jsonSerializer = new DataContractJsonSerializer(objs[i].GetType());
jsonSerializer.WriteObject(ms, objs[i]);
var objStr = Encoding.UTF8.GetString(ms.ToArray(), 0, (int)ms.Length);
ms.Position = 0;
sb.AppendFormat("p{0}=", i);
sb.AppendFormat("{0}", objStr);
sb.Append("&");
}
ms.Close();
paramStr = sb.ToString();
}
在此方法中主要是记录下这些信息,
另外把服务需要传入的参数序列化成JSON字符串
紧接着就调用InvokeService方法
代码如下
public void InvokeService()
{
Uri serviceUri = new Uri("http://localhost/RTMDemo.Host/RTMDemo.Host.WCF.MenuService");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(serviceUri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
var requestResult = request.BeginGetRequestStream(new AsyncCallback(RequestReady), request);
return;
}
明眼人一看就明了了
其实就是使用HTTPWebRequest来调用服务(服务端我们托管了HttpHandler的请求)
RequestReady事件如下:
void RequestReady(IAsyncResult asyncResult)
{
HttpWebRequest request = asyncResult.AsyncState as HttpWebRequest;
Stream stream = request.EndGetRequestStream(asyncResult);
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
StreamWriter writer = new StreamWriter(stream);
writer.Write(paramStr);
writer.Write("MethodKey=RTMDemo.Host.WCF.{0}.{1}&", className,methodName);
writer.Flush();
writer.Close();
request.BeginGetResponse(new AsyncCallback(ResponseReady), request);
});
}
在此事件中我们把服务类名方法名和参数写入了请求流
ResponseReady事件如下
void ResponseReady(IAsyncResult asyncResult)
{
HttpWebRequest request = asyncResult.AsyncState as HttpWebRequest;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult);
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
Stream responseStream = response.GetResponseStream();
if (resultType == null)
{
Completed(this, null);
return;
}
try
{
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(resultType);
result = jsonSerializer.ReadObject(responseStream);
}
catch
{
}
var se = new ServiceEventArgs();
se.Result = result;
Completed(this, se);
});
}
这个事件把服务端返回的结果(JSON数据)反序列化成实体类型,并赋值给ServiceEventArgs
然后触发了Completed事件
也就是触发我们服务端代理类的si_Completed事件
至此,调用服务端的类就解释完了
下面我们看看是怎么调用服务端的
private void InitMenu()
{
var ms = new MenuService();
ms.Completed += new ServiceEventHandler((o, re) =>
{
var AllMenu = re.Result as List<MenuM>;
Common.ViewUtility.AllMenu = AllMenu;
InitTopMenu();
});
ms.GetAllMenu();
}
看看是不是与ria service调用的方法有点像呢?
估计再写一篇就完结了
下一篇公布源码