Reputation: 2183
Have a look at the following code, where two methods throw same type of exception but have different context altogether.
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?
}
}
}
Problem which I am having with above catch
is that it catches exception of type X
from both the methods. But my high level logic requires to have different Response
objects (say, to have different language code, different message, different application specific code for exception cause) when X
exception comes from different method or you can say that Responose
should change according to the context.
What is the best way to achieve this?
Edit
Following code tells you why i want to do this
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??
}
}
Upvotes: 3
Views: 2308
Reputation: 273199
After the edit,
In the macro execute you have the opportunity to enrich or encapsulate the exception:
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;
}
}
}
And then when you handle the exception higher up, you can have your ICommand back from ex.Data["Command"]
The alternative is a class XWrapper : Exception
where you can add your own properties, and then replace the throw;
with throw new XWrapper(..., ex);
And of course you then have to catch(Xwrapper xObj) ...
outside the loop.
Upvotes: 1
Reputation: 592
There are two ways for this, one is to use xExceptionObj.StackTrace which contains complete call hierarchy, so from that info you can search for required details. This is preferred in case if more than one parent is calling same method and you like to handle it part of base class.
And then the easy one which I prefer for you simple case is to use TargetSite Object
xExceptionObj.TargetSite.Name
output will be "methodThrowingExceptionX"
Upvotes: 1
Reputation: 460068
The normal way is to surround both method calls with their own try...catch
. On that way you always know what caused the exception and you can handle it separately.
If you want to avoid that for whatever reason you could use the Exception.TargetSite
:
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);
}
}
Upvotes: 5
Reputation: 190905
The only clean way to achieve this is to have 2 try..catch
blocks, one around each call.
An ugly/unmaintainable/unruly solution would be to use status variables and you check for in the catch block.
Upvotes: 1