首先,请原谅任何错字,因为英语不是我的母语。
假设我想在我的应用程序中使用构造函数注入。例如,我会有类似的东西:
public class FileDataProvider : IDataProvider
{
public MyData GetData()
{
// Get data from a file
}
}
public class DatabaseDataProvider : IDataProvider
{
public MyData GetData()
{
// Get data from a database
}
}
public class DataReader : IDataReader
{
private IDataProvider dataProvider;
public DataReader(IDataProvider dataProvider)
{
this.dataProvider = dataProvider;
}
public void OutputData()
{
MyData data = dataProvider.GetData();
Console.WriteLine("{0}", data.ToString());
}
}
如果我使用构造函数注入,我根据定义没有控制或想法实现IDataProvider的类的具体实例将注入到我的DataReader类中。这意味着在我的DataReader类中我不知道GetData方法中发生了什么,包括我不知道它是否会抛出异常这一事实,如果是这样,那是什么样的异常。
在我的OutputData方法中,我应该将我的代码包装到try {} catch {}块中,如果是这样,我应该捕获什么异常?如果我捕获IOException或SQLException或实际上任何类型的异常意味着我在某种程度上预先设定了IDataProvider可能/应该实现的方式。我认为这不好。我也可以注入一个XMLDataProvider或NetworkResourceDataProvider。但与此同时,我必须在某些时候处理异常。
我的问题:在一般情况下使用控制反转和构造函数注入更具体地处理异常和记录应用程序中发生的事情的正确方法是什么?还有什么是正确的方法 - 如果有的话 - 在实现接口的类中抛出异常?
-
为我的问题添加一个精度,我不会拥有将实现IDataProvider的代码,所以我甚至不能确定会抛出一个自定义异常,比如DataProviderException
。即使我为开发人员编写指导原则......
答案 0 :(得分:7)
根据定义,如果您不知道如何处理异常,那么请不要捕获它。周期。
答案 1 :(得分:6)
在我看来,IDataProvider
的具体实现应该捕获适当的异常(文件提供者的I / O,数据库提供者的SQL)并引发另一个异常,该异常传达获取数据的一般错误,即{{{ 1}}。如果需要,您可以将原始异常存储为内部异常属性,以便信息不会丢失。
这样做DataProviderException
消费者只需要处理这个特殊的异常,并且不受细节的影响。这假设消费者有办法处理异常,即可以重试。
答案 2 :(得分:5)
首先让我说你的英语比我的法语好,所以t'inquietes pas de ca。
如果发生SQLException,你不会在代码中做一些特殊的事情,对吗?
一般情况下,除非您知道自己要做什么,否则不希望发现异常。例外通常可以让开发人员知道出了什么问题:这就是为什么你得到一个跟踪它的堆栈跟踪。因此,通常最好让它们冒泡到UI下方的某个点,您可以在其中记录它们并优雅地告诉用户发生了意外情况。