我正在为我的宠物软件构建API,我遇到以下情况:
使用其他服务的服务。我有一个服务使用另一个服务加载程序集,我应该在加载程序集的服务或使用该服务的服务上抛出异常吗?
AssemblyService:
public class AssemblyService : IAssemblyService
{
public Assembly Load(string assemblyName)
{
Assembly assembly;
try
{
assembly = Assembly.Load(assemblyName);
}
catch
{
assembly = null;
}
return assembly;
}
...
}
使用AssemblyService的服务:
public class CommandService : ICommandService
{
private readonly IAssemblyService assemblyService;
public CommandService(IAssemblyService assemblyService)
{
this.assemblyService = assemblyService;
}
public CommandOutput Process(string inputCommand, string requestInfo)
{
string commandName = GetAssemblyName(inputCommand);
string args = GetArgs(inputCommand);
Assembly assembly = assemblyService.Load(commandName);
if (assembly == null) throw new UnknownCommandException(commandName);
ICommand command = assemblyService.GetCommand(assembly);
return command.Execute(args, requestInfo);
}
#region Private methods
...
#endregion
}
我应该像上面的例子一样在AssemblyService或CommandService中抛出异常吗?
我正在尝试学习如何处理异常,在上面的示例中,行assembly = Assembly.Load(assemblyName);
可以抛出ArgumentNullException
,ArgumentException
,FileNotFoundException
,{{1} }和FileLoadException
。我应该处理所有这些例外吗?
BadImageFormatException
其他问题:任何使用我的API的人都知道某个方法何时会抛出异常?我看到将鼠标放在.Net Framework的任何方法上,您将看到该方法是否会引发异常。这可以用我的API方法吗?
答案 0 :(得分:5)
你的标题是关于抛出异常,但你实际上似乎在谈论捕获异常。除非你能做一些有意义的事情来纠正导致引发异常的条件,否则通常不应该捕获异常,在这种情况下,你应该只捕获你可以处理的显式异常类型。
答案 1 :(得分:2)
这里有两件事要考虑:
应用程序的正常流量是否会突然停止到不再有效的程度?例外就是这样 - 通知发生了异常(异常,异常等)。如果不是例外,请不要抛出异常。如果用户可以在不注意的情况下继续使用该程序,请不要使用例外。
如何评论方法声明会对此产生影响。应该有一些注释的标记标记,这些标记将允许您解释将抛出什么异常以及在什么情况下它将被抛出。它们看起来像这样:
/// <exception cref="ExceptionTypeGoesHere"></exception>
答案 2 :(得分:1)
api顾名思义是应用程序的网关。如果在api中发生错误,则api最有用的是告诉消费者错误发生的原因,地点和时间,即api抛出异常。消费者要抓住这个并告诉用户该做什么,或者如果业务逻辑定义得好,消费者将计算替代执行路径。这是我的经验法则
在上面的示例中,程序集加载服务应该抛出错误。如果你在api中处理这个问题,那么消费者将永远不会学习:)
有关异常处理的一般准则,请参阅Msdn
答案 3 :(得分:1)
我通常会尝试避免使用异常来控制程序的流程。您的程序使用异常将其转换为结果变量,然后将其转换回异常。为什么不一直坚持例外?我会改变如下:
public class AssemblyService : IAssemblyService
{
public Assembly Load(string assemblyName)
{
return Assembly.Load(assemblyName);
}
}
public class CommandService : ICommandService
{
private readonly IAssemblyService assemblyService;
public CommandService(IAssemblyService assemblyService)
{
this.assemblyService = assemblyService;
}
public CommandOutput Process(string inputCommand, string requestInfo)
{
string commandName = GetAssemblyName(inputCommand);
try
{
string args = GetArgs(inputCommand);
Assembly assembly = assemblyService.Load(commandName);
ICommand command = assemblyService.GetCommand(assembly);
return command.Execute(args, requestInfo);
}
catch (Exception ex)
{
//Log original exception or add to inner exception
throw new UnknownCommandException(commandName);
}
}
}