使用泛型封装返回结果以及使用委托封装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);
                }
});
posted @ 2013-07-18 16:51  YLWS  阅读(699)  评论(0编辑  收藏  举报