I have a following C# scenario-
I have to handle an exception in base class that actually occurs in the derived class.
My base class looks like this:
public interface A
{
void RunA();
}
public class Base
{
public static void RunBase(A a)
{
try
{
a.RunA();
}
catch { }
}
}
The derived class is as follows:
public class B: A
{
public void RunA()
{
try
{
//statement: exception may occur here
}
catch{}
}
}
I want to handle the exception, lets say exception C, that occurs in B(at //statement above).
The exception handling part should be written in base class catch inside RunBase. How can this be done?
public class Base
{
public static void RunBase(A a)
{
try
{
a.RunA();
}
catch(SomeSpecialTypeOfException ex)
{
// Do exception handling here
}
}
}
public class B: A
{
public void RunA()
{
//statement: exception may occur here
...
// Don't use a try-catch block here. The exception
// will automatically "bubble up" to RunBase (or any other
// method that is calling RunA).
}
}
How can this be done?
What do you mean? Just remove the try-catch block from RunA.
Having said that, you need to make sure Class A knows how to handle the exception, this includes streamlining it to UI, logging, ... This is in fact rare for a base class. Handling exception normally happen at the UI level.
public class B: A
{
public void RunA()
{
try
{
// statement: exception may occur here
}
catch(Exception ex)
{
// Do whatever you want to do here if you have to do specific stuff
// when an exception occurs here
...
// Then rethrow it with additional info : it will be processed by the Base class
throw new ApplicationException("My info", ex);
}
}
}
You also might want to throw the exception as it is (use throw alone).
If you dont need to process anything here, dont put try{} catch{}, let the exception bubble up by itself and be processed by the Base class.
Just remove the try catch from class B, if the exception occurs it will propergate up the call chain until it is handled. In this case you can handle the exception in RunBase using your existing try catch block.
Though in your example B isn't derived from your base class Base. If you really want to handle a situation where an exception is thrown in a derived class in its parent you could try something like:
public class A
{
//Public version used by calling code.
public void SomeMethod()
{
try
{
protectedMethod();
}
catch (SomeException exc)
{
//handle the exception.
}
}
//Derived classes can override this version, any exception thrown can be handled in SomeMethod.
protected virtual void protectedMethod()
{
}
}
public class B : A
{
protected override void protectedMethod()
{
//Throw your exception here.
}
}
Related
I am writing a method in c# class as shown below:
using(sftpClient)
{
sftpClient.Connect();
try{
//Do some process
}
catch(Exception ex)
{
}
sftpClient.Disconnect();
}
I need to create some more methods similar to the above but the logic changes only inside the try{} catch{} block. Can anyone suggest some best way to achieve this using some design pattern?
You could create an abstract base class:
abstract class MyBaseClass {
protected abstract void DoSomething();
public void DoSmtpStuff() {
smtpClient.Connect();
try {
DoSomething();
} catch (Exception ex) {
}
smtpClient.Disconnect();
}
}
and then just create inheritances of that class, which implement only the DoSomething method.
Take a look at the Strategy Pattern (emphasis my own):
In computer programming, the strategy pattern (also known as the
policy pattern) is a software design pattern that enables an
algorithm's behavior to be selected at runtime.
So basically, you would declare an interface, say, IBehaviour and define some method:
public interface IBehaviour
{
void Process();
}
Then have a different class implement IBehaviour for each piece of logic you want to have.
The class where you need to consume the logic would then allow passing an IBehaviour object and in your try block just do behaviour.Process().
This will allow you to set up the behaviour from outside the class and then simply pass it along to the class in which you want to actually do something with it.
Alternative to classes is just take Action as argument:
TResult WithSftpClient<TResult>(Func<TResult, SftpClient> operation)
{
TResult result = default(TResult);
// Note that one may need to re-create "client" here
// as it is disposed on every WithSftpClient call -
// make sure it is re-initialized in some way.
using(sftpClient)
{
sftpClient.Connect();
try
{
result = operation(sftpClient);
}
catch(Exception ex)
{
// log/retrhow exception as appropriate
}
// hack if given class does not close connection on Dispose
// for properly designed IDisposable class similar line not needed
sftpClient.Disconnect();
}
return result;
}
And use it:
var file = WithSftpClient(client => client.GetSomeFile("file.name"));
You can use this pattern:
abstract class ProcedureBase<T>
{
public T Work()
{
using(sftpClient)
{
sftpClient.Connect();
try{
ProtectedWork();
}
catch(Exception ex)
{
}
sftpClient.Disconnect();
}
}
protected abstract T ProtectedWork();
}
class Procedure1 : ProcedureBase<TypeToReturn>
{
protected override TypeToReturn ProtectedWork()
{
//Do something
}
}
class Procedure2 : ProcedureBase<AnotherTypeToReturn>
{
protected override AnotherTypeToReturn ProtectedWork()
{
//Do something
}
}
Usage:
static void Main(string[] args)
{
Procedure1 proc = new Procedure1();
proc.Work();
}
So I've created a custom exception class (let's call it CustomException) along with some custom properties not found in the Exception class. In the global.asax.cs file there is the Application_Error method that is called whenever an exception happens. I'm using Server.GetLastError() to grab the exception that triggered the Application_Error method. The problem is that Server.GetLastError() only grabs an Exception object and not the CustomException object that is being thrown along with its custom properties. Basically the CustomException is stripped down to an Exception object when retrieved by Server.GetLastError(), thus losing the custom properties associated with CustomException.
Is there a way for GetLastError() to actually retrieve the CustomException object and not the stripped down Exception version? This is needed in order to store the errors in a database table with more information than would normally be supplied by an Exception.
Application_Error:
protected void Application_Error(object sender, EventArgs e)
{
// This var is Exception, would like it to be CustomException
var ex = Server.GetLastError();
// Logging unhandled exceptions into the database
SystemErrorController.Insert(ex);
string message = ex.ToFormattedString(Request.Url.PathAndQuery);
TraceUtil.WriteError(message);
}
CustomException:
public abstract class CustomException : System.Exception
{
#region Lifecycle
public CustomException ()
: base("This is a custom Exception.")
{
}
public CustomException (string message)
: base(message)
{
}
public CustomException (string message, Exception ex)
: base(message, ex)
{
}
#endregion
#region Properties
// Would like to use these properties in the Insert method
public string ExceptionCode { get; set; }
public string SourceType { get; set; }
public string SourceDetail { get; set; }
public string SystemErrorId { get; set; }
#endregion
}
Just cast the Server.GetLastError's result to CustomException:
var ex = Server.GetLastError() as CustomException;
Remember that in some situations your CustomException could not be the top exception in the StackTrace, in this case you'll need to navigate through the InnerExceptions to find the right one.
Please, check the #scott-chamberlain links about how to design custom exceptions.
I want to write a test checking, whether my abstract classes constructor correctly handles invalid arguments. I wrote a test:
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void MyClassCtorTest()
{
var dummy = Substitute.For<MyClass>("invalid-parameter");
}
This test does not pass, because NSubstitute throws a TargetInvocationException instead of ArgumentException. The actual exception I seek for is actually an InnerException of that TargetInvocationException. I can write a helper method like:
internal static class Util {
public static void UnpackException(Action a) {
try {
a();
} catch (TargetInvocationException e) {
throw e.InnerException;
} catch (Exception) {
throw new InvalidOperationException("Invalid exception was thrown!");
}
}
}
But I guess, that there rather should be some kind of general way of solving that problem. Is there one?
NSubstitute does not currently have a general way of solving this.
Some other workarounds include manually subclassing the abstract class to test the constructor, or manually asserting on the inner exception rather than using ExpectedException.
For example, say we have an abstract class that requires a non-negative integer:
public abstract class MyClass {
protected MyClass(int i) {
if (i < 0) {
throw new ArgumentOutOfRangeException("i", "Must be >= 0");
}
}
// ... other members ...
}
We can create a subclass in a test fixture to test the base class constructor:
[TestFixture]
public class SampleFixture {
private class TestMyClass : MyClass {
public TestMyClass(int i) : base(i) { }
// ... stub/no-op implementations of any abstract members ...
}
[Test]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void TestInvalidConstructorArgUsingSubclass()
{
new TestMyClass(-5);
}
// Aside: I think `Assert.Throws` is preferred over `ExpectedException` now.
// See http://stackoverflow.com/a/15043731/906
}
Alternatively you can still use a mocking framework and assert on the inner exception. I think this is less preferable to the previous option as it is not obvious why we're digging in to the TargetInvocationException, but here's an example anyway:
[Test]
public void TestInvalidConstructorArg()
{
var ex = Assert.Throws<TargetInvocationException>(() => Substitute.For<MyClass>(-5));
Assert.That(ex.InnerException, Is.TypeOf(typeof(ArgumentOutOfRangeException)));
}
we have 2 custom class (baseClass and ChildClass) the child class has inherited from the baseClass
when we get a exception on childClass, OnException event on the baseClass should be called
it'll be like MVC Controller OnException Events
We will use for logging.
In the general case it is not possible to do. The MVC OnException works because the framework catches any unhandled exceptions and forwards them to OnException. The framework code for calling a controller action is something like:
try
{
controller.SomeAction();
}
catch(Exception ex)
{
controller.OnException(ex);
}
The entire implementation depends on the caller of the code taking the responsibility to handle the exceptions. With a general calls that can be used by any code you can't make any assumptions on how the class will be called.
If we somehow can make all calls go through the base class we can make something similar:
public class Base
{
public BlahaMethod()
{
try
{
DoBlaha();
}
catch(Exception ex)
{
OnException(ex);
}
}
protected abstract void DoBlaha();
private void OnException(Exception ex)
{
// Handle exception
}
}
public class Derived
{
protected virtual void DoBlaha()
{
throw new NotImplementedException();
}
}
You can catch exception with a try-catch-finally construct. The only general exception handler (known to me) is the unhandled exception handler in the appdomain.
I would like to automagically add the following code around the body of some methods:
try
{
// method body
}
catch (Exception e)
{
throw new MyException("Some appropriate message", e);
}
I am working with PostSharp 1.0 and this is what I've done at the moment:
public override void OnException(MethodExecutionEventArgs eventArgs)
{
throw new MyException("Some appropriate message", eventArgs.Exception);
}
My problem is that I can see the PostSharp OnException call in the stack.
What would be the good practice to avoid this and get the same call stack as implementing by hand the exception handler?
There is no way to hide "OnException" from the call stack.
Two things working in tandem will allow you to do this:
The fact that Exception.StackTrace is virtual
The use of the skipFrames parameter to the StackFrame constructor. This is not required, but makes things easier
The below example demonstrates how to customize the stack trace. Note that I know of no way to customize the Exception.TargetSite property, which still gives the details of the method from which the exception originated.
using System;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// exception is reported at method A, even though it is thrown by method B
MethodA();
}
private static void MethodA()
{
MethodB();
}
private static void MethodB()
{
throw new MyException();
}
}
public class MyException : Exception
{
private readonly string _stackTrace;
public MyException()
{
// skip the top two frames, which would be this constructor and whoever called us
_stackTrace = new StackTrace(2).ToString();
}
public override string StackTrace
{
get { return _stackTrace; }
}
}
}