I am inserting different message based on the exception type.
I want to insert different custom message into the exception table based on the exception type. I cant use switch statements with exception object.
Any suggestion on how I can do this?
private void ExceptionEngine(Exception e)
{
if (e.)
{
exceptionTable.Rows.Add(null, e.GetType().ToString(), e.Message);
}
if (e is NullReferenceException)
{
...
}
else if (e is ArgumentNullException)
{
...
}
else if (e is SomeCustomException)
{
...
}
else
{
...
}
and inside those if clauses you can cast e to the corresponding exception type to retrieve some specific properties of this exception: ((SomeCustomException)e).SomeCustomProperty
If all the code will be in the if/else blocks then better to use multiple catch (remember to put the most specific types first):
try {
...
} catch (ArgumentNullException e) {
...
} catch (ArgumentException e) { // More specific, this is base type for ArgumentNullException
...
} catch (MyBusinessProcessException e) {
...
} catch (Exception e) { // This needs to be last
...
}
I cant use switch statements with exception object.
If you want to use a switch, you could always use the Typename:
switch (e.GetType().Name)
{
case "ArgumentException" : ... ;
}
This has the possible advantage that you do not match subtypes.
You could unify the handling of different exception types (known at compile time) by a pre-defined dictionary. For example:
// Maps to just String, but you could create and return whatever types you require...
public static class ExceptionProcessor {
static Dictionary<System.Type, Func<String, Exception> sExDictionary =
new Dictionary<System.Type, Func<String, Exception> {
{
typeof(System.Exception), _ => {
return _.GetType().ToString();
}
},
{
typeof(CustomException), _ => {
CustomException tTmp = (CustomException)_;
return tTmp.GetType().ToString() + tTmp.CustomMessage;
}
}
}
public System.String GetInfo(System.Exception pEx) {
return sExDictionary[pEx.GetType()](pEx);
}
}
Usage:
private void ExceptionEngine(Exception e) {
exceptionTable.AddRow(ExceptionProcessor.GetInfo(e));
}
Related
I like to use a method for different kind of classes/types. I could do something like this:
public void ClearTable(string type)
{
try
{
using (var connection = new SQLiteConnection(platform, dbPath))
{
switch (type)
{
case "Project":
connection.DropTable<Project>();
connection.CreateTable<Project>();
break;
case "Task":
connection.DropTable<Task>();
connection.CreateTable<Task>();
break;
default:
break;
}
}
}
catch (SQLiteException ex)
{
Log.Info("SQLiteEx", ex.Message);
}
}
Where, for example "Project" in DropTable is a name of a class. But I prefer more something more generic like (this is the part where I am not sure what to do):
public void ClearTable(Type t)
{
try
{
using (var connection = new SQLiteConnection(platform, dbPath))
{
connection.DropTable<t>();
connection.CreateTable<t>();
}
}
catch (SQLiteException ex)
{
Log.Info("SQLiteEx", ex.Message);
}
}
How can I use something like the last method to support multiple kind of classes/types?
You are looking for Generics
With generics you could write code like this:
public void ClearTable<TType>()
{
try
{
using (var connection = new SQLiteConnection(platform, dbPath))
{
connection.DropTable<TType>();
connection.CreateTable<TType>();
}
}
catch (SQLiteException ex)
{
Log.Info("SQLiteEx", ex.Message);
}
}
You then can call the method and give any type as generic parameter:
ClearTable<MyDomainModel>();
In additition you could restrict the generic parameter TType with a where clause.
public void ClearTable<TType>()
where TType : IDomainModel
{
// your code goes here
}
Now you can only give types which inherit from IDomainModel as generic parameter.
Depends on what the code that calls ClearTable looks like.
Compile time binding
If it knows the type at compile time, you can change your prototype to
public void ClearTable<T>()
...and call it with
var myClass = new MyClass();
myClass.ClearTable<Task>();
or
myClass.ClearTable<Project>();
Run-time binding
If the type is not known until run-time, and you truly have to pass it as a string like that, you could set up a delegate dictionary like this:
class MyClass
{
private readonly Dictionary<string, Action<SQLLiteConnection>> _actions = new Dictionary<string, Action<SQLLiteConnection>>();
public MyClass()
{
_actions.Add("Project", conn => conn.DropTable<Project>());
_actions.Add("Task", conn => conn.DropTable<Task>());
}
public void ClearTable(string type)
{
try
{
using (var connection = new SQLiteConnection(platform, dbPath))
{
var action = _actions[type](connection);
action(connection);
}
}
catch (KeyNotFoundException ex1)
{
Log.Info(String.Format("{0} is not a supported type.", type));
}
catch (SQLiteException ex2)
{
Log.Info("SQLiteEx", ex2.Message);
}
}
}
This question already has answers here:
Is there a way to catch all unhandled exceptions thrown by a given class?
(6 answers)
Closed 8 years ago.
I have a lot of classes (WCF services) that contain several function. Now I need to handle errors, but I don't want to create a block try ... catch within each function (for error handling).
How can I make try...catch in any class (or something else) so that we catch errors but did not write the same block within each method?
There will always be some duplication of code but you can reduce it to one line
public static class ExceptionHandler
{
public static void Run(Action action)
{
try
{
a();
}
catch(Exception e)
{
//Do Something with your exception here, like logging
}
}
}
and then just call
ExceptionHandler.Run(yourAction);
you can add overloads for functions and what not but this approach is not ideal. As you may want to catch specific exceptions in certain cases.
Since you did not provide code specifically, I will write some sample code to make it more obvious. If you have this:
public class MyClass
{
public void Method1ThatCanThrowException()
{
try
{
// the Method1 code that can throw exception
}
catch (MySpecificException ex)
{
// some specific error handling
}
}
public object Method2ThatCanThrowException()
{
try
{
// the Method2 code that can throw exception
}
catch (MySpecificException ex)
{
// the same specific error handling
}
}
}
So, if you intend to have single place error handling, you can use lambda, and the help of a private method:
private T CheckAndCall<T>(Func<T> funcToCheck)
{
try
{
return funcToCheck();
}
catch (MySpecificException ex)
{
// the old specific error handling
}
}
Notice the use of the Func<T> delegate. This is because you may need to wrap the try-catch logic around some code that can return a value.
Then you can rewrite the above methods like this:
public void Method1ThatCanThrowException()
{
CheckAndCall(
() =>
{
// the Method1 code that can throw exception
return null;
});
}
public object Method2ThatCanThrowException()
{
return CheckAndCall(
() =>
{
// the Method2 code that can throw exception
return someObject;
});
}
For example, rather than having to do this:
public class Program
{
public static string ReadFile(string filename)
{
//A BCL method that throws various exceptions
return System.IO.File.ReadAllText(filename);
}
public static void Main(string[] args)
{
try
{
Console.Write(ReadFile("name.txt"));
}
catch (Exception e)
{
Console.WriteLine("An error occured when retrieving the name! {0}", e.Message);
}
try
{
Console.Write(ReadFile("age.txt"));
}
catch (Exception e)
{
Console.WriteLine("An error occured when retrieving the age! {0}", e.Message);
}
}
}
You could implement a "Try..." method, using the ref or out keyword as appropriate:
public class Program
{
public static bool TryReadFile(string filename, out string val)
{
try
{
val = System.IO.File.ReadAllText(filename);
return true;
}
catch (Exception)
{
return false;
}
}
public static void Main(string[] args)
{
string name, age;
Console.WriteLine(TryReadFile("name.txt", out name) ? name : "An error occured when retrieving the name!");
Console.WriteLine(TryReadFile("age.txt", out age) ? age: "An error occured when retrieving the age!");
}
}
The downside to this approach is that you can't act upon a specific exception, but in the case of simply determining if an operation has or has not succeeded, I find this to be a syntactically clean approach.
I want to do something like this in C#. I think this is possible using Delegates or Anonymous Methods. I tried but I couldn't do it. Need help.
SomeType someVariable = try {
return getVariableOfSomeType();
} catch { Throw new exception(); }
You can create a generic helper function:
static T TryCatch<T, E>(Func<T> func, Func<E, T> exception)
where E : Exception {
try {
return func();
} catch (E ex) {
return exception(ex);
}
}
which you can then call like so:
static int Main() {
int zero = 0;
return TryCatch<int, DivideByZeroException>(() => 1 / zero, ex => 0);
}
This evaluates 1 / zero within the context of TryCatch's try, causing the exception handler to be evaluated which simply returns 0.
I doubt this will be more readable than a helper variable and try/catch statements directly in Main, but if you have situations where it is, this is how you can do it.
Instead of ex => 0, you can also make the exception function throw something else.
You should do something like this:
SomeType someVariable;
try {
someVariable = getVariableOfSomeType();
}
catch {
throw new Exception();
}
SomeType someVariable = null;
try
{
someVariable = GetVariableOfSomeType();
}
catch(Exception e)
{
// Do something with exception
throw;
}
You can try this
try
{
SomeType someVariable = return getVariableOfSomeType();
}
catch { throw; }
SomeType someVariable = null;
try
{
//try something, if fails it move to catch exception
}
catch(Exception e)
{
// Do something with exception
throw;
}
Related
Related
I want to dynamically invoke a MethodInfo object and have any exceptions that get thrown from inside of it pass outward as if it were called normally.
I have two options it seems. They're outlined below.
Option 1 maintains the type of the exception thrown by MyStaticFunction, but the StackTrace is ruined because of the throw.
Option 2 maintains the StackTrace of the exception, but the type of the exception is always TargetInvocationException. I can pull out the InnerException and its type, but that means that I can't write this for example:
try { DoDynamicCall(); }
catch (MySpecialException e) { /* special handling */ }
Option 1:
void DoDynamicCall()
{
MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
try
{
method.Invoke(null, new object[] { 5 });
}
catch (TargetInvocationException e)
{
throw e.InnerException;
}
}
Option 2:
void DoDynamicCall()
{
MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
method.Invoke(null, new object[] { 5 });
}
What I really want is for callers to DoDynamicCall to receive exceptions as if they had called this:
void DoDynamicCall()
{
MyClass.MyStaticFunction(5);
}
Is there a way to get the benefits of both Option 1 and Option 2?
Edit:
The option I wish I had (invented special new C# keyword rethrow on the spot):
void DoDynamicCall()
{
MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
try
{
method.Invoke(null, new object[] { 5 });
}
catch (TargetInvocationException e)
{
//Magic "rethrow" keyword passes this exception
//onward unchanged, rather than "throw" which
//modifies the StackTrace, among other things
rethrow e.InnerException;
}
}
This would also eliminate the need for this weirdo, because you could use rethrow e; instead:
try { ... }
catch (Exception e)
{
if (...)
throw;
}
In general, it would be a way to decouple throw; from the requirement "I have to be directly in a catch block."
Here's the solution I came up with. It gets the job done. I'm still interested in other answers as there might be something easier or cleaner.
When you want the functionality of throw; but the exception you want to pass on is not the exception of the current catch block, use throw Functional.Rethrow(e);
Replace try...catch... with Functional.TryCatch
Replace try...catch...finally... with Functional.TryCatchFinally
Here's the code:
//Need a dummy type that is throwable and can hold an Exception
public sealed class RethrowException : Exception
{
public RethrowException(Exception inner) : base(null, inner) { }
}
public static Functional
{
public static Exception Rethrow(Exception e)
{
return new RethrowException(e);
}
public static void TryCatch(Action _try, Action<Exception> _catch)
{
try { _try(); }
catch (RethrowException e) { _catch(e.InnerException); }
catch (Exception e) { _catch(e); }
}
public static T TryCatch<T>(Func<T> _try, Func<Exception, T> _catch)
{
try { return _try(); }
catch (RethrowException e) { return _catch(e.InnerException); }
catch (Exception e) { return _catch(e); }
}
public static void TryCatchFinally(
Action _try, Action<Exception> _catch, Action _finally)
{
try { _try(); }
catch (RethrowException e) { _catch(e.InnerException); }
catch (Exception e) { _catch(e); }
finally { _finally(); }
}
public static T TryCatchFinally<T>(
Func<T> _try, Func<Exception, T> _catch, Action _finally)
{
try { return _try(); }
catch (RethrowException e) { return _catch(e.InnerException); }
catch (Exception e) { return _catch(e); }
finally { _finally(); }
}
}
Update
In .NET 4.5 there is the new System.Runtime.ExceptionServices.ExceptionDispatchInfo class. This can be used to capture an exception:
var capturedException = ExceptionDispatchInfo.Capture(e);
And then later this is used to resume throwing the exception:
capturedException.Throw();
No, I don't believe there is a way to have the benefits of both. However, throwing e.InnerException will still allow you to get the original stacktrace, because you can simply use e.InnerException.StackTrace to get the original stack trace. So, in short, you should use option 1.
The best option is Option 3: don't use reflection at all, but instead use Expression<T>.Compile().
Instead of doing this:
static void CallMethodWithReflection(MethodInfo method)
{
try
{
method.Invoke(null, new object[0]);
}
catch (TargetInvocationException exp)
{
throw exp.InnerException;
}
}
Try to aim for this:
private static void CallMethodWithExpressionCompile(MethodInfo method)
{
Expression.Lambda<Action>(Expression.Call(method)).Compile()();
}
The caveat is that you need to know the method signature, although you can write code that dynamically builds the expression to fit one of several signatures.
You may not always be able to use this technique, but when you do it is the best option. For all intents and purposes it is like calling any other delegate. It is also faster than reflection if you make multiple calls (in this case compile only once and keep a handle on the compiled delegate).
I had a similar issue and came up with this:
/// <summary>
/// Attempts to throw the inner exception of the TargetInvocationException
/// </summary>
/// <param name="ex"></param>
[DebuggerHidden]
private static void ThrowInnerException(TargetInvocationException ex)
{
if (ex.InnerException == null) { throw new NullReferenceException("TargetInvocationException did not contain an InnerException", ex); }
Exception exception = null;
try
{
//Assume typed Exception has "new (String message, Exception innerException)" signature
exception = (Exception) Activator.CreateInstance(ex.InnerException.GetType(), ex.InnerException.Message, ex.InnerException);
}
catch
{
//Constructor doesn't have the right constructor, eat the error and throw the inner exception below
}
if (exception == null ||
exception.InnerException == null ||
ex.InnerException.Message != exception.Message)
{
// Wasn't able to correctly create the new Exception. Fall back to just throwing the inner exception
throw ex.InnerException;
}
throw exception;
}
An Example of it's use is below:
try
{
return typeof(MyType).GetMethod(methodName, BindingFlags.Public | BindingFlags.Static)
.MakeGenericMethod(new[] { myType) })
.Invoke(null, parameters);
}
catch (TargetInvocationException ex)
{
ThrowInnerException(ex);
throw new Exception("Throw InnerException didn't throw exception");
}
I'm working with some classes which, when throwing, have a relatively deep InnerException tree. I'd like to log and act upon the innermost exception which is the one having the real reason for the problem.
I'm currently using something similar to
public static Exception getInnermostException(Exception e) {
while (e.InnerException != null) {
e = e.InnerException;
}
return e;
}
Is this the proper way to handle Exception trees?
I think you can get the innermost exception using the following code:
public static Exception getInnermostException(Exception e) {
return e.GetBaseException();
}
You could use the GetBaseException method.
Very quick example:
try
{
try
{
throw new ArgumentException("Innermost exception");
}
catch (Exception ex)
{
throw new Exception("Wrapper 1",ex);
}
}
catch (Exception ex)
{
// Writes out the ArgumentException details
Console.WriteLine(ex.GetBaseException().ToString());
}
In a word, yes. I cannot think of any significantly better or different way of doing it. Unless you wanted to add it as an extension method instead, but it's really six of one, half-a-dozen of the other.
There are exceptions that can have multiple root causes (e.g. AggregateException and ReflectionTypeLoadException).
I created my own class to navigate the tree and then different visitors to either collect everything or just the root causes. Sample outputs here. Relevant code snippet below.
public void Accept(ExceptionVisitor visitor)
{
Read(this.exception, visitor);
}
private static void Read(Exception ex, ExceptionVisitor visitor)
{
bool isRoot = ex.InnerException == null;
if (isRoot)
{
visitor.VisitRootCause(ex);
}
visitor.Visit(ex);
visitor.Depth++;
bool isAggregateException = TestComplexExceptionType<AggregateException>(ex, visitor, aggregateException => aggregateException.InnerExceptions);
TestComplexExceptionType<ReflectionTypeLoadException>(ex, visitor, reflectionTypeLoadException => reflectionTypeLoadException.LoaderExceptions);
// aggregate exceptions populate the first element from InnerExceptions, so no need to revisit
if (!isRoot && !isAggregateException)
{
visitor.VisitInnerException(ex.InnerException);
Read(ex.InnerException, visitor);
}
// set the depth back to current context
visitor.Depth--;
}
private static bool TestComplexExceptionType<T>(Exception ex, ExceptionVisitor visitor, Func<T, IEnumerable<Exception>> siblingEnumerator) where T : Exception
{
var complexException = ex as T;
if (complexException == null)
{
return false;
}
visitor.VisitComplexException(ex);
foreach (Exception sibling in siblingEnumerator.Invoke(complexException))
{
visitor.VisitSiblingInnerException(sibling);
Read(sibling, visitor);
}
return true;
}