方法即服务 — 2. 解耦服务器宿主

传送门

方法即服务 — 1. 思考

既然希望业务代码在不同的服务器宿主环境下执行,那么就需要抽象不同服务器宿主之间的行为差异,解耦服务器宿主与业务代码之间的关系

概要设计

无论是任何服务器宿主host)与客户端client)的交互都摆脱不了

Request → Process → Response

的套路,区别在于不同的 Host 产生的 Request 不同,需要返回的 Response 也不一样;

至于Process,在.NET中无非就是

Instance + Properties + Arguments + Method + Result

例如:

var method = FindMethod();
var instance = CreateInstance(method.ReflectedType);
var props = GetProperties();
instance.SetProps(props);
var arguments = GetArguments();
var result = method.invoke(instance,arguments);

所以我需要一个对象用于获得 Process 五件套参数,我决定抽象一个 IRequest 对象,IRequest对象就包含了刚才例子中的 FindMethod,GetProperties,GetArguments几个方法;
这样我就可以简单的实现一个通用的 Process 方法了

public object Process(IRequest request)
{
    var request = GetRequest();
    var method = request.FindMethod();
    var instance = Activator.CreateInstance(method.ReflectedType);
    var props = request.GetProperties();
    foreach(var prop in props)
    {
        method.ReflectedType.GetProperty(prop.Name).SetValue(instance, prop.Value);
    }
    var arguments = request.GetArguments();
    var result = method.invoke(instance, arguments);
    return result;
}

好吧,我知道这代码看起来容错性非常差,但不必在意,就当这只是在画草图。

有了这样一个通用的 Process 方法,那么只需要在不同的服务器宿主环境下构建一个 IRequest 就可以了,把这个工作交给适配器Adapter)去做,所以这个流程看上去就这样的:

WebRequest → WebAdapter → IRequest → Process → Result → WebAdapter → WebResponse

或是

RpcRequest → RpcAdapter → IRequest → Process → Result → RpcAdapter → RpcResponse

服务器宿主接收到请求之后,通过特定 Adapter 将原本的 Request 转为刚刚自定义的 IRequest 对象,然后通过 Process 方法执行请求,得到返回值之后再次经过 Adapter 的处理,将 object Result 转为指定类型的 Response 返回给客户端;

在MVC下代码大致就是这样的:

internal class MisRouteHandler : IHttpHandler, IRouteHandler
{
    private MvcAdapter _adapter;

    public MisRouteHandler(string urlTemplate)
    {
        _adapter = new MvcAdapter(urlTemplate);
    }

    public bool IsReusable => true;

    public void ProcessRequest(HttpContext httpContext)
    {
        try
        {
            var request = _adapter.CreateRequest(httpContext);
            var result = Mis.Process(request);
            var response = _adapter.ConvertToResponse(result);
            httpContext.Response.StatusCode = response.StatusCode;
            httpContext.Response.ContentType = response.ContentType;
            foreach (var header in response.headers)
            {
                httpContext.Response.Headers.Set(header.name, header.value);
            }
            if (response.content != null)
            {
                httpContext.Response.BinaryWrite(response.content);
            }
        }
        catch (Exception e)
        {
            httpContext.Response.ContentType = "text/plain;charset=utf-8";
            httpContext.Response.StatusCode = 500;
            httpContext.Response.BinaryWrite(Encoding.UTF8.GetBytes(e.ToString()));
        }
    }

    IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) => this;
}

流程图

方法即服务 — 2. 解耦服务器宿主_第1张图片

未完待续……

你可能感兴趣的:(方法即服务 — 2. 解耦服务器宿主)