看看下面的代码,其中两个方法抛出相同类型的异常,但总共有不同的上下文。
class Test
{
public void methodThrowingExceptionX()
{
//some code
throw new X();
}
public void anotherMethodThrowingExceptionX()
{
//some code
throw new X();
}
}
class TestClient
{
private Test testObj = new Test();
public Response TestMethodCaller()
{
try
{
testObj.methodThrowingExceptionX();
testObj.anotherMethodThrowingExceptionX();
}
catch(X xExceptionObj)
{
//this will catch X exception regardless from which method it is comming
//How can i distinguish from where the exception is coming(which method is throwing)
//so that i can return the Response object according to the context of the method which has thrown this exception?
}
}
}
我在catch
之上遇到的问题是它从这两种方法中捕获了类型X
的异常。但是,当Response
异常来自不同的方法时,我的高级逻辑需要具有不同的X
对象(例如,具有不同的语言代码,不同的消息,异常原因的不同应用程序特定代码),或者您可以说Responose
应根据上下文进行更改。
实现这一目标的最佳方法是什么?
修改
以下代码告诉您我为什么要这样做
interface ICommand
{
void execute();
}
//say we have some command implementation
class CommandA : ICommand
{
public void execute()
{
//some code
throw new X();
}
}
class CommandB : ICommand
{
public void execute()
{
//some code
throw new X();
}
}
class MacroCommand : ICommand
{
List<ICommand> commands;
public MacroCommand(List<ICommand> commands)
{
this.commands = commands;
}
public void execute()
{
foreach(ICommand command in commands)
{
//execute method of various commands can throw exceptions may of same type say X.
command.execute();
}
}
}
class Client
{
List<ICommand> commands = new List<ICommand>();
commands.Add(new CommandB());
commands.Add(new CommandA());
MacroCommand macroCommand = new MacroCommand(commands);
try
{
macroCommand.execute();
}
catch(X xExceptionObj)
{
//How can i get the information which execute() actually thrown the exception??
}
}
答案 0 :(得分:5)
通常的方法是用自己的try...catch
包围两个方法调用。在这种情况下,你总是知道导致异常的原因,你可以单独处理它。
如果你想以任何理由避免这种情况
try
{
testObj.methodThrowingExceptionX();
testObj.anotherMethodThrowingExceptionX();
}
catch (X xExceptionObj)
{
MethodBase site = xExceptionObj.TargetSite;
switch (site.Name)
{
case nameof(testObj.methodThrowingExceptionX):
return blah....
case nameof(testObj.anotherMethodThrowingExceptionX):
return blub....
default:
throw new Exception("Unexpected method caused exception: " + site.Name);
}
}
答案 1 :(得分:1)
实现此目标的唯一干净方法是拥有2个try..catch
块,每个呼叫一个。
一个丑陋/不可维护/不守规矩的解决方案是使用状态变量,并在catch块中检查。
答案 2 :(得分:1)
有两种方法,一种是使用包含完整调用层次结构的xExceptionObj.StackTrace,因此可以从该信息中搜索所需的详细信息。如果多个父级调用相同的方法并且您希望将其作为基类的一部分处理,则首选。
然后,我更喜欢的简单案例就是使用TargetSite Object
xExceptionObj.TargetSite.Name
答案 3 :(得分:1)
编辑后,
在宏执行中,您有机会丰富或封装异常:
public void execute()
{
foreach(ICommand command in commands)
{
try
{
command.execute();
}
catch(X ex)
{
// add one or more command related pieces of info to the exception
ex.Data.Add("Command", command.Name);
throw;
}
}
}
然后当您处理更高的异常时,可以从ex.Data["Command"]
替代方案是class XWrapper : Exception
,您可以在其中添加自己的属性,然后将throw;
替换为throw new XWrapper(..., ex);
当然,您必须在循环外部catch(Xwrapper xObj) ...
。