使用泛型封装返回结果以及使用委托封装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);
}
});