zoukankan      html  css  js  c++  java
  • SilverLight企业应用框架设计【三】服务端设计

    一:缓存服务类型与方法

    客户端请求的时候

    为了方便的知道请求的类型与类型所包含的方法

    我们把服务类型和方法缓存到静态字典中了

    代码如下

        public class WCFRouteTable
        {
            static Dictionary<string, Type> routeService;
            static Dictionary<string, MethodInfo> routeMethods;
            static WCFRouteTable()
            {
                routeService = new Dictionary<string, Type>();
                routeMethods = new Dictionary<string, MethodInfo>();
                var ass = (typeof(WCFRouteTable)).Assembly;
                var ts = ass.GetTypes();
                foreach (var t in ts)
                {
                    if (t.FullName.StartsWith("RTMDemo.Host.WCF"))
                    {
                        routeService.Add(t.FullName, t);
                        foreach (var m in t.GetMethods())
                        {
                            var mName = string.Format("{0}.{1}", t.FullName, m.Name);
                            routeMethods.Add(mName, m);
                        }
                    }
                }
            }
            public static Type GetWCFType(string key)
            {
                Type result = null;
                if (routeService.ContainsKey(key))
                {
                    result = routeService[key];
                }
                return result;
            }
            public static MethodInfo GetMethodInfo(string key)
            {
                MethodInfo result = null;
                if (routeMethods.ContainsKey(key))
                {
                    result = routeMethods[key];
                }
                return result;
            }
    
        }

    二:托管HTTP请求

    在webconfig中增加module以托管请求

        <modules>
                <add name="WcfHttpModule" type="RTMDemo.Host.WCFHttpModule, RTMDemo.Host"/>
        </modules>

    托管请求对应的类的代码如下

        public class WCFHttpModule:IHttpModule
        {
            public void Dispose() { }
            /// <summary>
            /// 托管请求
            /// </summary>
            /// <param name="context"></param>
            public void Init(HttpApplication context)
            {
                context.BeginRequest += (sender, args) =>
                {
                    string relativeAddress = HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.Remove(0, 2);
                    Type serviceType = WCFRouteTable.GetWCFType(relativeAddress);
                    if (null == serviceType)
                    {
                        return;
                    }
                    IHttpHandler handler = new WCFHandler(serviceType);
                    context.Context.RemapHandler(handler);
                };
            }
        }

    通过这行代码

    Type serviceType = WCFRouteTable.GetWCFType(relativeAddress);

    用户只要请求如下路径

    http://localhost/RTMDemo.Host/RTMDemo.Host.WCF.MenuService

    就会得到MenuService的类型

    然后把服务类型传给指定的处理程序

    三:处理请求

    在WCFHandler类中最重要的莫过于

    处理请求的方法

    代码如下

    /// <summary>
            /// 处理请求
            /// </summary>
            /// <param name="context"></param>
            public void ProcessRequest(HttpContext context)
            {
                try
                {
                    List<object> paramList = new List<object>();
                    JavaScriptSerializer jss = new JavaScriptSerializer();
                    var MethodKey = context.Request["MethodKey"];
                    var minfo = WCFRouteTable.GetMethodInfo(MethodKey);
                    var si = new MethodInvoker(minfo);
                    ParameterInfo[] ps = minfo.GetParameters();
                    var pstrs = context.Request.Form.AllKeys.OrderBy(m=>m).ToArray();
                    var pIndex = 0;
                    for(var i=0;i<pstrs.Length;i++)
                    {
                        if (string.IsNullOrEmpty(pstrs[i]))
                        {
                            continue;
                        }
                        if (pstrs[i].StartsWith("p"))
                        {
                            var pStr = context.Request[pstrs[i]];
                            var obj = jss.Deserialize<object>(pStr);
                            var bts = Encoding.UTF8.GetBytes(pStr);
                            MemoryStream mss = new MemoryStream(Encoding.UTF8.GetBytes(pStr));
                            DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(ps[pIndex].ParameterType);                
                            var p = jsonSerializer.ReadObject(mss);
                            paramList.Add(p);
                            pIndex += 1;
                        }
                    }
    
                    //todo:此处性能不佳
                    var instance = Activator.CreateInstance(ServiceType);
                    var result = si.Execute(instance,paramList.ToArray());
                    var ss = jss.Serialize(result);
    
                    context.Response.ClearContent();
                    context.Response.ContentEncoding = Encoding.UTF8;
                    context.Response.ContentType = "application/json; charset=utf-8";
                    context.Response.Write(ss);
                    context.Response.Flush();
                }
                catch
                {
                    context.Response.Write("我们不提供此服务的元数据~<br />");
                    context.Response.Write("@@@@@@~<br />@@@@@@@~");
                    return;
                }
            }
        }

    注意:首先说这段代码还有很大的优化空间;也未经过严格的测试;但思路基本就是这样的

    处理请求主要做了如下几步工作:

    1.

    先根据请求POST上来的信息得到准备执行的方法

    var MethodKey = context.Request["MethodKey"];
    var minfo = WCFRouteTable.GetMethodInfo(MethodKey);

    MethodInvoker稍后再讲

    2.

    按顺序取出了方法的参数,并用DataContractJsonSerializer反序列化成对象

    方法参数都是用JSON字符串传递的

    3.

    通过反射创建了服务的实例

    然后调用该实例的方法

    得到方法的返回值,并序列化成JSON字符串

    4.

    把返回值以JSON的形式输出给客户端

    四:其他

    1.

    MethodInvoker是用的老赵的类;具体是哪篇文章,我已经找不到了。

    public class MethodInvoker
        {
            private Func<object, object[], object> m_execute;
    
            public MethodInvoker(MethodInfo methodInfo)
            {
                this.m_execute = this.GetExecuteDelegate(methodInfo);
            }
    
            public object Execute(object instance, params object[] parameters)
            {
                return this.m_execute(instance, parameters);            
            }
    
            private Func<object, object[], object> GetExecuteDelegate(MethodInfo methodInfo)
            {
                ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "instance");
                ParameterExpression parametersParameter = Expression.Parameter(typeof(object[]), "parameters");
    
                List<Expression> parameterExpressions = new List<Expression>();
                ParameterInfo[] paramInfos = methodInfo.GetParameters();
                for (int i = 0; i < paramInfos.Length; i++)
                {
                    var ce = Expression.Constant(i);
                    BinaryExpression valueObj = Expression.ArrayIndex(parametersParameter,ce);
                    UnaryExpression valueCast = Expression.Convert(valueObj, paramInfos[i].ParameterType);
                    parameterExpressions.Add(valueCast);
                }
                var instanceE = Expression.Convert(instanceParameter, methodInfo.ReflectedType);
                Expression instanceCast = methodInfo.IsStatic ? null : instanceE;
                MethodCallExpression methodCall = Expression.Call(instanceCast, methodInfo, parameterExpressions);
                if (methodCall.Type == typeof(void))
                {
                    Expression<Action<object, object[]>> lambda = Expression.Lambda<Action<object, object[]>>(methodCall, instanceParameter, parametersParameter);
                    Action<object, object[]> execute = lambda.Compile();
                    return (instance, parameters) =>
                    {
                        execute(instance, parameters);
                        return null;
                    };
                }
                else
                {
                    UnaryExpression castMethodCall = Expression.Convert(methodCall, typeof(object));
                    Expression<Func<object, object[], object>> lambda =Expression.Lambda<Func<object, object[], object>>(castMethodCall, instanceParameter, parametersParameter);
                    return lambda.Compile();
                }
            }
        }

    2.

    服务类和数据访问的类没有什么特殊的

    我这里只公布一个服务的类

        public class MenuService
        {
            public List<MenuM> GetAllMenu()
            {            
                using (var DA = new MenuDA())
                {
                    var result = DA.GetAllMenu();
                    return result;
                }
            }
            public void DelMenu(Guid Id)
            {
                using (var DA = new MenuDA())
                {
                    DA.DelMenu(Id);
                }
            }
            public void AddMenu(MenuM m)
            {
                using (var DA = new MenuDA())
                {
                    DA.AddMenu(m);
                }
            }
            public void UpdateMenu(MenuM m)
            {
                using (var DA = new MenuDA())
                {
                    DA.UpdateMenu(m);
                }
            }
        }

    MenuDa就是数据访问类了

    很普通,就不在公布代码了

    3.

    完成这些工作之后

    我们只要在客户端构造好表单

    然后把表单POST到指定的路径

    就能完成服务的访问了!

    ---------------------------------------------------------------

    喜欢的话~请大家推荐我的文章

    谢谢~

    我真的很需要你们的支持

  • 相关阅读:
    组织过程资产
    事业环境因素
    一起来学习Android自定义控件2-简单的写字板控件
    Android自定义控件1
    一起来学习Android自定义控件1
    Java你可能不知道的事(3)HashMap
    Java你可能不知道的事(3)HashMap
    Java你可能不知道的事(3)HashMap
    java你可能不知道的事(2)--堆和栈
    java你可能不知道的事(2)--堆和栈
  • 原文地址:https://www.cnblogs.com/liulun/p/2313674.html
Copyright © 2011-2022 走看看