自己开发的公众号,可以领取淘宝内部优惠券

问题

现在有一个FileStorageService类,继承自IStorageService,具体实现如下

public interface IStorageService
{
void WriteAllBytes(string path, byte[] buffer);
byte[] ReadAllBytes(string path);
} public class FileStorageService : IStorageService
{
public void WriteAllBytes(string path, byte[] buffer) {
File.WriteAllBytes(path, buffer);
} public byte[] ReadAllBytes(string path)
{
return File.ReadAllBytes(path);
}
}

假设调用其中任一一个方法出现异常,例如读写文件时候经常碰见的异常:IOExceptionDirectoryNotFoundExceptionFileNotFoundException,UnauthorizedAccessException… 甚至是 OutOfMemoryException

方案1-不是我的问题

IStorageService 不关心抛出的异常,那是使用者的职责。如此便将问题抛给了使用IStorageService接口的用户,它们必须要捕获有可能抛出的异常,往往一种偷懒的做法就是使用try catch语句将其包裹起来,如:

IStorageService myStorageService = Resolver.Resolve<IStorageService>();
try
{
myStorageService.ReadAllBytes("C:\stuff.data");
} catch (Exception exception)
{
// please don't write generic error messages like this, be specific
Logger.Log("Oops something went wrong: " + exception.Message);
}

catch exception并不是什么好主意,而且每次调用都需要使用try catch很不方便

方案2-创建新的异常类

一种改进的方法就是创建我们自己的异常类如StorageReadException,不管以后具体的实现如何变化,我们仅捕获特定的异常来进行异常处理

public class StorageReadException : Exception
{
public StorageReadException(Exception innerException)
: base(innerException.Message, innerException)
{
}
}

之前的FileStorageService实现更改为:

public byte[] ReadAllBytes(string path)
{
try
{
return File.ReadAllBytes(path);
}
catch (FileNotFoundException fileNotFoundException)
{
throw new StorageReadException(fileNotFoundException);
}
}

调用代码:

IStorageService myStorageService = Resolver.Resolve<IStorageService>();
try
{
myStorageService.ReadAllBytes(path);
}
catch (StorageReadException sre)
{
Logger.Log(String.Format("Failed to read file from path, {0}: {1}", path, sre.Message));
}

同样存在try catch 包裹问题,而且用户必须依赖一个新的异常类型

方案3-Try 模式并返回一个Complex Result

我们可以使用Try模式来避免用户使用try catch,Try模式类似C#里int方法

bool TryParse(string s, out int result),我们对接口进行更改

byte[] ReadAllBytes(string path)

变为

bool TryReadAllBytes(string path, out byte[] result)

但是这样不能提供用户更多的错误信息。如果我们想要显示更多的有帮助的异常信息给用户,可以返回一个通用的结果类OperationResult<TResult>

public class OperationResult<TResult>
{
private OperationResult ()
{
} public bool Success { get; private set; }
public TResult Result { get; private set; }
public string NonSuccessMessage { get; private set; }
public Exception Exception { get; private set; } public static OperationResult<TResult> CreateSuccessResult(TResult result)
{
return new OperationResult<TResult> { Success = true, Result = result};
} public static OperationResult<TResult> CreateFailure(string nonSuccessMessage)
{
return new OperationResult<TResult> { Success = false, NonSuccessMessage = nonSuccessMessage};
} public static OperationResult<TResult> CreateFailure(Exception ex)
{
return new OperationResult<TResult>
{
Success = false,
NonSuccessMessage = String.Format("{0}{1}{1}{2}", ex.Message, Environment.NewLine, ex.StackTrace),
Exception = ex
};
}
}

FileStorageService的ReadAllBytes 方法变为

public OperationResult<byte[]> TryReadAllBytes(string path)
{
try
{
var bytes = File.ReadAllBytes(path);
return OperationResult<byte[]>.CreateSuccessResult(bytes);
}
catch (FileNotFoundException fileNotFoundException)
{
return OperationResult<byte[]>.CreateFailure(fileNotFoundException);
}
}

调用代码:

var result = myStorageService.TryReadAllBytes(path);
if(result.Success)
{
// do something
}
else
{
Logger.Log(String.Format("Failed to read file from path, {0}: {1}", path, result.NonSuccessMessage));
}

原文:Error Handling in SOLID C# .NET – The Operation Result Approach

错误处理(Operation Result)方法的更多相关文章

  1. InnoDB: Operating system error number 87 in a file operation. 错误87的解决方法

    InnoDB: Operating system error number 87 in a file operation. 错误87的解决方法 140628  8:10:48 [Note] Plugi ...

  2. coreseek常见错误原因及解决方法

    coreseek常见错误原因及解决方法 Coreseek 中文全文检索引擎 Coreseek 是一款中文全文检索/搜索软件,以GPLv2许可协议开源发布,基于Sphinx研发并独立发布,专攻中文搜索和 ...

  3. android 真机调试出现错误 INSTALL_FAILED_INSUFFICIENT_STORAGE 的解决方法。

    关于这个神奇的 内存不够错误的通常解决方法,网上大把,建议大家在尝试过了网上的方法后再来尝试下我的这种方法. 编译工具: android studio 测试真机:米 2 调试的时候出现:INSTALL ...

  4. 无法打开物理文件xxx.mdf操作系统错误 5:“5(拒绝访问。)” (Microsoft SQL Server,错误: 5120)的解决方法

    无法打开物理文件xxx.mdf操作系统错误 5:“5(拒绝访问.)” (Microsoft SQL Server,错误: 5120)的解决方法   问题描述: 在附加数据库到sql server时,附 ...

  5. 错误:Unsupported major.minor version 51.0(jdk版本错误)的解决方法

    错误:Unsupported major.minor version 51.0(jdk版本错误)的解决方法 java.lang.UnsupportedClassVersionError: org/ap ...

  6. 批处理命令篇--配置免安装mysql 5.6.22, 以及1067错误的一个解决方法

    mysql 服务启动出现1067错误的一个解决方法: 当服务启动出现1067错误时,可查看“windows 事件查看器”,发现类似错误提示 Can't find messagefile 'F:\    ...

  7. IIS发布网站浏览之后看到的是文件目录 & Internal Server Error 处理程序“ExtensionlessUrlHandler-ISAPI-4.0_64bit”在其模块列表中有一个错误模块“IsapiModule” 解决方法 & App_global.asax.pduxejp_.dll”--“拒绝访问。 ”

    Q:IIS发布网站浏览之后看到的是文件目录 A:它出现了一个说到.NET4.0 更高框架什么的错误,所以我将 .NTE CRL版本由4.0改为2.0了,改为2.0后就出现了只能浏览文件目录了.改为4. ...

  8. ORA-04091错误原因与解决方法

    最近工作中写了一触发器报错:ORA-04091:table XX  is mutating, trigger/function may not see it. 下面通过官方文档及网友提供资料分析一下错 ...

  9. Eclipse进度条出现“Remote System Explorer Operation”解决方法

    Eclipse进度条出现“Remote System Explorer Operation”解决方法  

随机推荐

  1. java java 内部类

    java 内部类 一.java内部类: java内部类分为: 成员内部类.静态嵌套类.方法内部类.匿名内部类 . 内部类的共性: (1).内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.c ...

  2. ubuntu - 安装sqoop

    解析过程 参考:https://www.cnblogs.com/qingyunzong/p/8807252.html#_label4 一.下载 二.解压到指定目录 三.配置sqoop环境变量并生效 四 ...

  3. (Python OpenGL)【5】平移 PyOpenGL

    (Python OpenGL) 原文:http://ogldev.atspace.co.uk/www/tutorial06/tutorial06.html  (英文) 下面是我翻译过来的: 背景 在本 ...

  4. Centos7安装MySQL8.0

    请到这个地址看:https://www.cnblogs.com/kevingrace/p/10482469.html Centos7安装MySQL8.0 - 操作手册 一.yum安装方式: 卸载之前版 ...

  5. mybatis和jdbc分析

    从这个图上可以看出mybatis的整体执行图 jdbc的 mybatis对很多类型进行了转化,减少了开发的量

  6. Linux软件源apt 仓库 包 的概念

    概念介绍: 软件源是debian系的概念,把软件放在一个pool里面,用一条命令就可以自动从指定服务器下载并安装. 源列表是/etc/apt/sources.list,里面写了你所用的服务器地址 (其 ...

  7. echarts设置线条粗细

    series: [ { name:"buy", type:'line', data:[], itemStyle: { normal: { color: '#6cb041', lin ...

  8. 基本数据类型 list and tuple 04

    列表和元组 一,列表 1.列表 由[]括起来 可以存放各种数据类型:  存放量比较大 2.列表的索引和切片  列表也有索引 lst [i] i 即列表中各元素的位置 2.1列表的切片 lst[star ...

  9. Python读写操作Excel模块_xlrd_xlwt_xlutils

    Python 读写操作Excel -- 安装第三方库(xlrd.xlwt.xlutils.openpyxl) 如果仅仅是要以表单形式保存数据,可以借助 CSV 格式(一种以逗号分隔的表格数据格式)进行 ...

  10. Vue.js递归组件实现动态树形菜单

    使用Vue递归组件实现动态菜单 现在很多项目的菜单都是动态生成的,之前自己做项目也是遇到这种需求,翻看了官网案例,和网上大神的案例.只有两个感觉,官网的案例太简洁,没有什么注释,看起来不太好理解,大神 ...