zoukankan      html  css  js  c++  java
  • 使用泛型封装返回结果以及使用委托封装try-catch流程

    有一个很常见的需求,服务端有一个 校验登陆的 方法,最开始只有一个布尔值,表示成功失败。

    public bool UserValid(string name, string pwd)
    {
         //校验登陆  
    }
    

    后来需求变更,需要返回 具体的User对象以及 登陆失败的原因。

    方案一:返回标识 比如 0,1,2 或者是枚举 表示登陆状态,在界面上再转化为具体的 登陆成功,密码错误等。
    方案二:在方法中添加 out message,返回错误信息。
    方案三:服务端抛出对应异常,客户端捕获。
    方案四:封装返回结果为一个类。

    个人偏向方案四,但是如果每个返回结果都需要封装一个类,那不累死了?
    所以 使用泛型封装出一个通用的返回结果

        //定义返回状态
        public enum RequestState
        {
            Non = 0,
            Success = 1,
            Other = 2
        }
    
        //返回结果类
        public class Request<T>
        {
            public T Result { get; private set; }//具体结果
            public RequestState State { get; private set; }//状态
            public string ErrorMessage { get; private set; }//错误信息
    
            public Request(T result, RequestState state, string errorMessage)
            {
                this.Result = result;
                this.State = state;
                this.ErrorMessage = errorMessage;
            }
    
            public Request(T result, RequestState state)
                : this(result, state, "")
            {
    
            }
        }
    

    该类 包含三部分,泛型结果,状态枚举以及错误信息。
    这时我们可以将 上面的方法签名改为

    public Request<User> UserValid(string name, string pwd)
    

    客户端调用的时候 大致代码,此处使用winform

                try
                {
                    this.Cursor = Cursors.WaitCursor;
                    Request<User> request = IUser.UserValid(name, pwd);
                    if (request.State == RequestState.Success)
                    {
                        //dosomething
                    }
                    else
                    {
                        MessageBox.Show(request.ErrorMessage);
                    }
                }
                catch (Exception e)
                {
                    //catch                             
                }
                finally
                {
                    this.Cursor = Cursors.Default;
                }        

    一切运转良好。但是随着时间的推移,我们发现除了 dosomething处,其他的代码都是重复的,是时候再次封装了。
    我们使用委托将不同的操作抽离出来,将相同的操作封装为一个委托方法。

    void Execute<T>(Func<Request<T>> func, Action<Request<T>> action)
            {
                try
                {
                    this.Cursor = Cursors.WaitCursor;
                    Request<T> request = func();
                    if (request.State == RequestState.Success)
                    {
                        action(request);
                    }
                    else
                    {
                        MessageBox.Show(request.ErrorMessage);
                    }
                }
                catch (Exception e)
                {
                    //catch                            
                }
                finally
                {
                    this.Cursor = Cursors.Default;
                }
            }
    

    调用方法如下:

    Execute<User>(() => IUser.UserValid(name,pwd), /*获取数据*/ user=>MessageBox.Show(user.Name)/*后续处理*/);

    这就是我比较偏向方案四的原因,可以提供统一的接口规范。

    我们成功的将try中的逻辑分离了出来,使得我们只需要关注具体的实现。
    同样的将catch中的逻辑分离出来,根据捕获到的不同异常,做不同的处理,再次修改代码如下:

    void Execute<T>(Func<Request<T>> func, Action<Request<T>> action, Action<Exception> cactch)
            {
                try
                {
                    this.Cursor = Cursors.WaitCursor;
                    Request<T> request = func();
                    if (request.State == RequestState.Success)
                    {
                        action(request);
                    }
                    else
                    {
                        MessageBox.Show(request.ErrorMessage);
                    }
                }
                catch (Exception e)
                {
                    cactch(e);//此处需要捕获不同的异常 ,显示不同的错误               
                }
                finally
                {
                    this.Cursor = Cursors.Default;
                }
            }
    
            void Execute<T>(Func<Request<T>> func, Action<Request<T>> action)
            {
                Execute<T>(func, action, e => MessageBox.Show(e.Message));
            }       

    调用方法:

    Execute<User>(() => IUser.UserValid(name,pwd), /*获取数据*/ user=>MessageBox.Show(user.Name)/*后续处理*/,ex=>{
                    if (ex is SocketException)
                    {
                        //.......
                    }
                    else//最后所有的异常类型
                    {
                        MessageBox.Show(ex.Message);
                    }
    });
  • 相关阅读:
    ios version和build
    协议
    masonry
    加密
    coredata
    随机附魔笔记
    Mac下搭建AzerothCore遇到的坑
    cocospods 私服搭建
    网络营销工具
    WKWebView不能重定向打开新界面,解决办法
  • 原文地址:https://www.cnblogs.com/ylws/p/3198544.html
Copyright © 2011-2022 走看看