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

问题

现在有一个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. vmware vmware esxi5.x安装方法及解决错误

    vmware Esxi5.x安装指南 vmware Esxi5文档中心官网地址: http://pubs.vmware.com/vsphere-55/index.jsp?topic=%2Fcom.vm ...

  2. metasploit 读书笔记-EXPLOITATION

    一、渗透攻击基础 1.常用命令 show exploits 显示Meta框架中所有可用的渗透攻击模块。 show options 显示模块所需要的各种参数 back 返回Meta的上一个状态 sear ...

  3. ubuntu安装软件-笔记

    手动安装过程 下载 - 配置文件 常用命令: sudo  dpkg -i ******.deb 问题&解决思路 问题1:依赖项 - 缺少某一个依赖包 解决尝试: 1 . sudo apt-ge ...

  4. utf-8-BOM删除bom

    utf-8  bom,去除bom //开始 function file_bom($wenjian,$remove = true) { //读取文件,将文件写入字符串    $contents = fi ...

  5. ios中的奇怪崩溃Signal和EXC_BAD_ACCESS错误分析

    什么是Signal 在计算机科学中,信号(英语:Signals)是Unix.类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式.它是一种异步的通知机制,用来提醒进程一个事件已经发 ...

  6. luogu1632 点的移动

    其实只需要开三重循环 根据OI中的一个重要的原理 给定一个序列a,求一个数x使得\(\sum |a_i-x|\)最小,那么这个数是序列a的中位数 证明略 然后既然是中位数,一定是数列中的数,类比到这题 ...

  7. 13.Convert BST to Greater Tree(将树转为更大树)

    Level:   Easy 题目描述: Given a Binary Search Tree (BST), convert it to a Greater Tree such that every k ...

  8. Infiniband交换机的FabricMonitor加载数据hang

    刚刚帮客户将Exadata中Infiniband交换机的固件版本从2.1.3-1 升级到2.2.7-1,但升级后发现Infiniband交换机的FabricMonitor功能无法使用,具体如下图所示. ...

  9. c语言定义指针类型需注意事项

    1)在定义说明语句中,指针变量名之前的星号“*“是指针变量的修饰符,也就是说它所修饰的变量是指针变量. 2)指针变量是用它们所指向的对象类型来区分的.如定义 int *ip,类型int并不是指针的类型 ...

  10. jquery 拖动改变div大小

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...