Catch derived class Exceptions in base class with different methods and arguments - c#

I'm trying to make something like base "exception handler" thing. So this base class will try-catch exceptions when any method (with any number of parameters) in derived class gets invoked. I'm not good in describing this with words, so here is the scenario:
public abstract BaseClass
{
Exception _ex;
public Exception LastKnownException
{
get
{
return this._ex;
}
}
//...
//what do I do here to assign the value of above property when some random exception occur in derived class?
//...
//The closest I can get...
public void RunMethod(Action method)
{
try
{
method.Invoke();
}
catch (Exception ex)
{
this._ex = ex;
}
}
}
public class DerivedClass : BaseClass
{
public void DoRandomMethod(int couldBeOfAnyTypeHere, bool andIndefiniteNumberOfThese)
{
bool result = false;
var someObject = new OtherClass(couldBeOfAnyTypeHere, out andIndefiniteNumberOfThese);
someObject.DoInternalWork(result); // <-- here is where I need the base class to take care if any exception should occur
}
public int AnotherMethod(int? id)
{
if (!id.HasValue)
id = Convert.ToInt32(Session["client_id"]);
var someOtherObject = new OtherClassB(id.Value);
return someOtherObject.CheckSomething(); // <-- and catch possible exceptions for this one too
}
//The closest I can get... (see base class implementation)
public List<RandomClass> GetSomeListBy(int id)
{
RunMethod(() =>
string[] whateverArgs = new[] { "is", "this", "even", "possible?" };
YetAnotherStaticClass.GetInstance().ExecuteErrorProneMethod(whateverArgs); // <-- Then when something breaks here, the LastKnownException will have something
);
}
}
public class TransactionController : Controller
{
public ActionResult ShowSomething()
{
var dc = new DerivedClass();
dc.DoRandomMethod(30, true);
if (dc.LastKnownException != null)
{
//optionally do something here
return RedirectToAction("BadRequest", "Error", new { ex = dc.LastKnownException });
}
else
{
return View();
}
}
}
EDIT: My simple approach will work, only, I don't want to have to wrap all methods with this lambda-driven RunMethod() method all the time -- I need the base class to somehow intercept any incoming exception and return the Exception object to the derived class without throwing the error.
Any ideas would be greatly appreciated. And thanks in advance!

I think you should consider using the event System.AppDomain.UnhandledException
This event will be raised whenever an exception occurs that is not handled.
As you don't clutter your code with the possibilities of exception, your code will be much better readable. Besides it would give derived classes the opportunity to catch exceptions if they expect ones, without interfering with your automatic exception catcher.
Your design is such, that if someone calls several functions of your derived class and then checks if there are any exceptions the caller wouldn't know which function caused the exception. I assume that your caller is not really interested in which function causes the exception. This is usually the case if you only want to log exception until someone investigates them.
If that is the case consider doing something like the following:
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = e.ExceptionObject as Exception;
if (ex != null)
logger.LogException(ex);
// TODO: decide whether to continue or exit.
}
If you really want to do this only for your abstract base class
public abstract BaseClass
{
private List<Exception> unhandledExceptions = new List<Exception>();
protected BaseClass()
{
AppDomain.CurrentDomain.UnhandledException += UnhandledException;
}
private void UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = e.ExceptionObject as Exception;
if (ex != null)
this.UnhandledExceptions.Add(ex);
}
public List<Exception> LastKnownExceptions
{
get { return this.unhandledExceptions; }
}

I had a similar requirement for catching exceptions, but used a specific implementation (i.e. not an abstract class) to encapsulate the handling of errors.
Please note this takes in an argument for any expected exceptions (params Type[] catchableExceptionTypes), but of course you can modify to suit your own requirements.
public class ExceptionHandler
{
// exposes the last caught exception
public Exception CaughtException { get; private set; }
// allows a quick check to see if an exception was caught
// e.g. if (ExceptionHandler.HasCaughtException) {... do something...}
public bool HasCaughtException { get; private set; }
// perform an action and catch any expected exceptions
public void TryAction(Action action, params Type[] catchableExceptionTypes)
{
Reset();
try
{
action();
}
catch (Exception exception)
{
if (ExceptionIsCatchable(exception, catchableExceptionTypes))
{
return;
}
throw;
}
}
// perform a function and catch any expected exceptions
// if an exception is caught, this returns null
public T TryFunction<T>(Func<T> function, params Type[] catchableExceptionTypes) where T : class
{
Reset();
try
{
return function();
}
catch (Exception exception)
{
if (ExceptionIsCatchable(exception, catchableExceptionTypes))
{
return null;
}
throw;
}
}
bool ExceptionIsCatchable(Exception caughtException, params Type[] catchableExceptionTypes)
{
for (var i = 0; i < catchableExceptionTypes.Length; i++)
{
var catchableExceptionType = catchableExceptionTypes[i];
if (!IsAssignableFrom(caughtException, catchableExceptionType)) continue;
CaughtException = caughtException;
HasCaughtException = true;
return true;
}
return false;
}
static bool IsAssignableFrom(Exception exception, Type type)
{
if (exception.GetType() == type) return true;
var baseType = exception.GetType().BaseType;
while (baseType != null)
{
if (baseType == type) return true;
baseType = baseType.BaseType;
}
return false;
}
void Reset()
{
CaughtException = null;
HasCaughtException = false;
}
}

Related

Calling extension method's overload with derived type

Simplified, i have these 2 Extension method:
public static class Extensions
{
public static string GetString(this Exception e)
{
return "Standard!!!";
}
public static string GetString(this TimeoutException e)
{
return "TimeOut!!!";
}
}
And here is where i use them:
try
{
throw new TimeoutException();
}
catch (Exception e)
{
Type t = e.GetType(); //At debugging this a TimeoutException
Console.WriteLine(e.GetString()); //Prints: Standard
}
I have more GetString() extensions.
My try{...}catch{...} is getting large and basically i search for ways to shorten it down to 1 catch that calls the extension based on the type of the exception.
Is there a way to call the right extension method at runtime?
As Yacoub Massad suggests you can use dynamic, because with dynamic method overload resolution is deferred at runtime through late binding.:
public static class Extensions
{
public static string GetString<T>(this T e) where T : Exception
{
// dynamic method overload resolution is deferred at runtime through late binding.
return GetStringCore((dynamic)e);
}
static string GetStringCore(Exception e)
{
return "Standard!!!";
}
static string GetStringCore(TimeoutException e)
{
return "TimeOut!!!";
}
static string GetStringCore(InvalidOperationException e)
{
return "Invalid!!!";
}
}
This should make the trick.
Extension methods are the wrong tool here.
I would foster the use of polymorphism to solve your problem:
public abstract class BaseException : Exception
{
public abstract string GetString();
}
public sealed class TimeoutException : BaseException
{
public override string GetString() => "TimeOut!!!";
}
public sealed class MyException : BaseException
{
public override string GetString() => "Standard!!!";
}
Usage
try
{
throw new TimeoutException(); //or whatever BaseException's children
}
catch (BaseException e)
{
//here I'm assuming you know that you are swallowing the exception (which may be an anti-pattern)
Console.WriteLine(e.GetString());
}
Edit
It looks like you have not the full control over which and when exceptions are thrown. Another possibility would be to add 1 catch clause for each behavior (rather than for each exception type) and get rid of GetString():
try
{
throw new TimeoutException();
}
catch (Exception e) when (e is ArgumentNullException || e is FormatException)
{
//do something
}
catch (Exception e) when (e is TimeoutException)
{
//do something
}
catch (Exception e)
{
throw new NotImplementedException($"Hey Mike, write something for {e.GetType()}, will ya?"); //idea from Jeroen
}

how to implement an early return (or override return) with void Method rather bool()

i was trying to do something like the code below to avoid using a Boolean return type method, and i couldn't find any way to implement it correctly:
public void myMethod(int someInitializingParameter)
{
//return (kinda override operator)
if(TargetObjToinitItsProperties == null) MsgDbgWinShow("Error: Line#637-xxx.CS", "Property was accessed prior to parent object init");
TargetObjToInitItsProperties.IntProp1 = someInitializingParameter;
}
static void MsgDbgWinShow(string Wtitle, string Wmsg)
{
create a window (windowsTitle=Wtitle .. size width ...create TextBlock.Content= Wmsg...etc')
CreatedWindow.Show();
//here is self exit and return ...from self but will not act as return operator...
}
is there any approach to use void as return type rather using a Type?
You could simply throw an exception and catch it in the caller.
That leaves the method at the point you put the 'throw':
public void myMethod(int someInitializingParameter)
{
//return (kinda override operator)
if(TargetObjToinitItsProperties == null)
throw new Exception("Property was accessed prior to parent object init");
TargetObjToInitItsProperties.IntProp1 = someInitializingParameter;
}
You could even create your own type of exception, when you inherit from it. Then you can put in some extra data:
class MyException : Exception
{
// some enhancements
public string ExtraData;
public MyException(string sMessage, string sExtraData)
: base(sMessage)
{
ExtraData = sExtraData;
}
}
Now you can throw it:
public void myMethod(int someInitializingParameter)
{
//return (kinda override operator)
string sExtraData = "Hallo";
if (TargetObjToinitItsProperties == null)
throw new MyException("Property was accessed prior to parent object init",
sExtraData);
TargetObjToInitItsProperties.IntProp1 = someInitializingParameter;
}
And in the caller you can catch it and use the extra data:
public void CallingMethod()
{
try
{
myMethod(23);
}
catch (MyException e)
{
Console.WriteLine(e.Message + e.ExtraData);
}
}

how can i set return so it accepts class1 or class2?

how can i, in my function start to fill the parameters for the class it is supposed to return, but if an exception occurs i'll return my error class instead?
public **** function()
{
try
{
Articles articles = new Articles();
articles.articleid = 234;
articles.articlename = "Milk";
articles.deleted = 0;
//continue fill Articles
//and an exception occurs
return articles;
}
catch (Exception e)
{
Errors Error = new Errors();
Error.exceptionmessage = e.Message;
Error.exceptionname = e.ToString();
Error.httpcode = 500;
return Error;
}
}
is this possible and a good thing to do? or should i just extend all return classes with my error class, even though i will return much info with allot of null values.
i would like to send as little data as possible and if my function fails i'll just send back the error.
UPDATE
sorry for not giving enough inforamtion about my situation this is a function that i want to use in a webservice
[OperationContract]
[WebGet(
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
**** Function();
so i dont think i can just throw an exception. i would like to return a class of articles if all is well so i dont have to convert my data to JSON but if something goes wrong i would like to send http code 500 Internal Server Error to the client.
i have not yet read all answers but i think i'll have to include my error class in all my other return classes so the client can now when something went wrong?
UPDATE:
That gives more insight on what you want to do. Since you can't throw exceptions, you should have a base result class. I usually do this for WCF methods I call through javascript, since it can't handle the exceptions nicely.
So you'll want a base class like:
[DataContract]
public class AjaxResult
{
public static AjaxResult GetSuccessResult()
{
return new AjaxResult();
}
[DataMember]
public int Status { get; set; }
[DataMember]
public string Error { get; set; }
}
Then you can inherit this, adding any data you would want to return. This example returns a single product object and a list of validation errors.
[DataContract]
public class SingleProductResult : AjaxResult
{
[DataMember]
public Product Data { get; set; }
[DataMember]
public IList<int> ValidationErrors { get; set; }
}
You can also opt to create a generic wrapper so you don't have to write to much code in your methods. I usually put this in a base class and let all WCF services inherit from that class.
protected T PerformAjaxOperation<T>(Func<T> action) where T : AjaxResult, new()
{
try
{
return action();
}
catch (AccessDeniedException ade)
{
// -- user tried to perform an invalid action
return new T()
{
Status = AjaxErrorCodes.AccessDenied,
Error = ade.ToString()
};
}
catch (Exception ex)
{
return new T()
{
Error = ex.ToString(),
Status = 1
};
}
}
Then just use it like so:
public SingleProductResult GetProduct(int productId)
{
return PerformAjaxOperation(() =>
{
return retval = new SingleProductResult()
{
Data = ProductServiceInstance.GetProduct(productId)
};
});
}
public AjaxResult DeleteProduct(int productId)
{
return PerformAjaxOperation(() => {
ProductServiceInstance.DeleteProduct(productId);
return AjaxResult.GetSuccessResult();
});
}
So, if everything proceeds smoothly, error will be 0 and message will be null. If an exception is thrown, then it will be caught by the PerformAjaxOperation() function and stuffed inside the AjaxResult object (or a derivative of it) and return to the client.
Previous answer:
I don't think this is a good idea. What you can do is create a custom exception by creating a class that inherits from Exception and add properties there that you want to save. Then when an exception occurs, you just catch it and stuff it inside this new exception along with other details. Then throw this exception instead. You can then catch this exception in the higher levels and display the proper message.
an example:
public IList<Articles> GetArticles()
{
try
{
return GetSomeArticlesFromDatabase();
}
catch (Exception innerException)
{
throw new MyCustomException("some data", 500, innerException);
}
}
public class MyCustomException : Exception
{
public int HttpCode { get; set; }
public MyCustomException(string errorMessage, int httpCode, Exception innerException)
: base(errorMessage, innerException) {
HttpCode = httpCode;
}
}
public void EntryPoint()
{
try
{
DoSomething();
var result = GetArticles();
DoSomething();
DisplayResult(result);
}
catch (MyCustomException ex)
{
ReturnHttpError(ex.Message, ex.HttpCode);
}
}
I would honestly advise against doing what you suggest. Instead, either use an existing Exception type or create a new subclass of Exception and throw it. You can even retain the causing exception information in the new exception's InnerException if so desired.
If the situation does not warrant an exception, however (you have not given enough details about what you are doing), you can create a Result class that contains error/warning information. This kind of thing would be better suited for warnings, though. That is, it is not an error condition that prevents things from continuing (exception), but instead a message that the calling code could choose to ignore without drastic side-effects.
For example:
class Result<T>
{
public Result(T Value, Errors Errors = null)
{
this.Value = Value;
this.Errors = Errors;
}
public T Value {get; private set;}
public Errors Errors {get; private set;}
}
Usage (as per your example code):
public Result<Articles> function()
{
try
{
Articles articles = new Articles();
articles.articleid = 234;
articles.articlename = "Milk";
articles.deleted = 0;
//continue fill Articles
//and an exception occurs
return new Result(articles);
}
catch (Exception e)
{
Errors Error = new Errors();
Error.exceptionmessage = e.Message;
Error.exceptionname = e.ToString();
Error.httpcode = 500;
return new Result<Articles>(null, Error);
}
}
If class1 and class2 have a common base type or common interface, use that. But in this case, you could create a wrapper class to encapsulate both result types, like this:
class MethodResult<T>
{
public T Result { get; private set; }
public Errors Errors { get; private set; }
public MethodResult(T result) { this.Result = result; }
public MethodResult(Errors errors) { this.Errors = errors; }
}
public MethodResult<Articles> MyMethod()
{
try
{
...
return new MethodResult<Articles>(articles);
}
catch(Exception e)
{
...
return new MethodResult<Articles>(errors);
}
}
In light of additional information in the question, since this is a WCF service, you could throw a WebFaultException:
public Articles function()
{
try
{
Articles articles = new Articles();
articles.articleid = 234;
articles.articlename = "Milk";
articles.deleted = 0;
//continue fill Articles
//and an exception occurs
return articles;
}
catch (Exception e)
{
throw new WebFaultException(System.Net.HttpStatusCode.InternalServerError)
{
Message = e.Message
};
}
}
The ways that other answers have handled this involve technical methods of how to define the two classes, using interfaces and subclassing.
However, fundamentally you're actually solving the wrong problem. You will still need to write code in the caller that distinguishes between the two types of object, as well as documenting the way in which your function works.
Personally, I would create a new Exception class for the type of error you may be handling, and throw that instead, for example:
public class InvalidArticleException: Exception {
public string ExceptionMessage { get; set; }
public string ExceptionName { get; set; }
public int HttpCode { get; set; }
}
public **** function()
{
try
{
// DO STUFF
return articles;
}
catch (InvalidArgumentException e)
{
throw new InvalidArticleException() {
ExceptionMessage = e.Message,
ExceptionName = e.ToString(),
HttpCode = 500
}
}
catch (Exception ex) { // Not actually required; left in for future debugging
throw ex;
}
}
Callers would then be able to catch the exception and examine it for the error details, with code that is kept separated from that which processes the returned articles.
You can try out keyword,
public Articles function(out Error err)
{
Articles articles = null;
err = null;
try
{
articles = new Articles();
articles.articleid = 234;
articles.articlename = "Milk";
articles.deleted = 0;
// Set your article values
}
catch (Exception e)
{
Errors ex = new Errors();
ex.exceptionmessage = e.Message;
ex.exceptionname = e.ToString();
ex.httpcode = 500;
err = ex;
}
return articles;
}
I'm not sure why would you want swallowing the exeptions, but if you do whatn this behgaviour make a return type common for both type. The both classes inherit from object so you can change the method signature to public object function()

Is it possible to catch an exception you can't handle (in C#)?

I have a generic class that catches exceptions of T:
public abstract class ErrorHandlingOperationInterceptor<T> : OperationInterceptor where T : ApiException
{
private readonly Func<OperationResult> _resultFactory;
protected ErrorHandlingOperationInterceptor(Func<OperationResult> resultFactory)
{
_resultFactory = resultFactory;
}
public override Func<IEnumerable<OutputMember>> RewriteOperation(Func<IEnumerable<OutputMember>> operationBuilder)
{
return () =>
{
try
{
return operationBuilder();
}
catch (T ex)
{
var operationResult = _resultFactory();
operationResult.ResponseResource = new ApiErrorResource { Exception = ex };
return operationResult.AsOutput();
}
};
}
}
With subclasses for specific exceptions e.g.
public class BadRequestOperationInterceptor : ErrorHandlingOperationInterceptor<BadRequestException>
{
public BadRequestOperationInterceptor() : base(() => new OperationResult.BadRequest()) { }
}
This all seems to work perfectly. But, somehow, in the logs (once, not every time) is an InvalidCastException:
System.InvalidCastException: Unable to cast object of type 'ErrorHandling.Exceptions.ApiException' to type 'ErrorHandling.Exceptions.UnexpectedInternalServerErrorException'.
at OperationModel.Interceptors.ErrorHandlingOperationInterceptor`1.c__DisplayClass2.b__1() in c:\BuildAgent\work\da77ba20595a9d4\src\OperationModel\Interceptors\ErrorHandlingOperationInterceptor.cs:line 28
Line 28 is the catch.
What am I missing? Have I done something really dumb?
As smithy said, your T is of type ApiErrorResource. You are, some where in your code, attempting to create your ErrorHandlingOperationInterceptor with an Exception that is NOT derived from ApiErrorResource.
try
{
// throw Exception of some sort
}
catch (BadRequestException ex)
{
BadRequestOperationInterceptor broi = new BadRequestOperationInterceptor ();
}
catch (Exception ex)
{
// this is NOT right
BadRequestOperationInterceptor broi = new BadRequestOperationInterceptor ();
}

Get thrown exception in finally block

Is there a way, how to get currently thrown exception (if exists)?
I would like reduce amount of code and apply some reuse for task looks like:
Exception thrownException = null;
try {
// some code with 3rd party classes, which can throw unexpected exceptions
}
catch( Exception exc ) {
thrownException = exc;
LogException( exc );
}
finally {
if ( null == thrownException ) {
// some code
}
else {
// some code
}
}
and replace it with this code:
using( ExceptionHelper.LogException() ) {
// some code with 3rd party classes, which can throw unexpected exceptions
}
using( new ExceptionHelper { ExceptionAction = ()=> /*some cleaning code*/ } ) {
// some code with 3rd party classes, which can throw unexpected exceptions
}
public class ExceptiohHelper : IDisposable {
public static ExceptionHelper LogException() {
return new ExceptionHelper();
}
public Action SuccessfulAction {get; set;}
public Action ExceptionAction {get; set;}
public void Dispose() {
Action action;
Exception thrownException = TheMethodIDontKnow();
if ( null != thrownException ) {
LogException( thrownException );
action = this.ExceptionAction;
}
else {
action = this.SuccessfulAction;
}
if ( null != action ) {
action();
}
}
}
Is this scenario posible?
Thanks
The idea is that you handle exceptions in the catch block...
That said, Exception is a reference type, so you can always declare an Exception variable outside the try scope...
Exception dontDoThis;
try
{
foo.DoSomething();
}
catch(Exception e)
{
dontDoThis = e;
}
finally
{
// use dontDoThis...
}
What do you think about the following. Instead of looking at the problem as "How to get the last exception?", what if you change it to, "How do I run some piece of code with some more control?"
For example:
Instead of an ExceptionHelper you could have an ActionRunner.
public class ActionRunner
{
public Action AttemptAction { get; set; }
public Action SuccessfulAction { get; set; }
public Action ExceptionAction { get; set; }
public void RunAction()
{
try
{
AttemptAction();
SuccessfulAction();
}
catch (Exception ex)
{
LogException(ex);
ExceptionAction();
}
}
private void LogException(Exception thrownException) { /* log here... */ }
}
It would at least give you some reuse of the SuccessfulAction and ExceptionAction assuming only the AttemptAction varies between calls.
var actionRunner = new ActionRunner
{
AttemptAction = () =>
{
Console.WriteLine("Going to throw...");
throw new Exception("Just throwing");
},
ExceptionAction = () => Console.WriteLine("ExceptionAction"),
SuccessfulAction = () => Console.WriteLine("SuccessfulAction"),
};
actionRunner.RunAction();
actionRunner.AttemptAction = () => Console.WriteLine("Running some other code...");
actionRunner.RunAction();
If you are looking to catch unexpected exceptions you should be handling the UnhandledException. You should only catch exceptions at lower levels that you intend handle (not just to log), otherwise you should let them bubble up and be caught at a higher level, or as I mentioned before in the UnhandledException method.

Categories

Resources