2

I'm not quite sure how to pose this questions. I really hope I can explain what my problem is properly.

I have multiple custom-exceptions distributed in my windows-service which I want to give back to the main process which initiates the process steps.

I have the static class PropertyMapper for example, which uses reflection to read email-headers and reflects them unto specific properties. Now if an exception turns up I want to add additional Information. Like what headerattribute actually caused the exception, but I don't want to lose the "actual" exception.

Currently it looks like this:

try
{
    PropertyInfo pInfo = prop.Property;
    Type t = Nullable.GetUnderlyingType(pInfo.PropertyType) ?? pInfo.PropertyType;
    object safeValue = (headerAttribute.Value == null) ? null : Convert.ChangeType(headerAttribute.Value, t);
    pInfo.SetValue(mailDataObj, safeValue, null);
}
catch (Exception e)
{
    throw new PropertyMappingFailedException(headerAttribute.Field, headerParam);
}

I throw the Exception to carry it back to the main process so that I only have to implement the "create logEntry-logic" once. ´

try
{
    mailDataObj = PropertyMapper.MapProperties(mailItem);
    mailDataObj.MailItem = mailItem;
    controller = new DAKMailController(mailDataObj);

    controller.SetBasicData(procFile);
    controller.HandlePostProcessing();
}
catch (Exception e)
{
    controller.CreateLogEntry(e);
    moveFileToError(file);
}

Now of course the exception that I originally cought is lost, because I don't add it to my custom exception, but how do I do that anyways? Also, is my way of thinking right or do I have to process exceptions in another way?

I already googled a little, but wasn't able to found something helpful. I'd appreciate some help. :)

P.S. I extract all InnerExceotions inside of the CreateLogEntry-method and put them into a single string-var.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
brocrow
  • 65
  • 1
  • 5

2 Answers2

3

Wrap the original exception in the field InnerException like this (in the catch of your first code sample):

throw new PropertyMappingFailedException(headerAttribute.Field, headerParam)
{ InnerException = e };
Terje Kolderup
  • 367
  • 3
  • 12
  • Ah, oh. Is it possible to send the inner exception as a parameter to the constructor (another overload than you are using)? – Terje Kolderup Feb 29 '16 at 12:00
  • `throw new CustomException("My message",ex)` this is syntax you are talking about stacktrace is string – Sebastian 506563 Feb 29 '16 at 12:02
  • Sending it to the constructor is the usual way, but I don't know PropertyMappingFailedException. See for instance this: http://stackoverflow.com/questions/4761216/c-throwing-custom-exception-best-practices – Terje Kolderup Feb 29 '16 at 12:02
  • Worst case, create your own PropertyMappingFailedException with InnerException as parameter in the constructor. – Terje Kolderup Feb 29 '16 at 12:18
1

Normally you do not add exceptions to each other but you sum stacktrace when:

throw ex, then stracktrace is gone, (reset) but when you use:

throw then it doesn't.

Also you are always catching all kind of exceptions but you are not adding stacktrace. Best practice looks more like that:

class Foo
{
    DoSomething(int param)
    {
        try 
        {
             if (/*Something Bad*/)
             {  
                 //violates business logic etc... 
                 throw new FooException("Reason...");
             }
             //... 
             //something that might throw an exception
        }
        catch (FooException ex)
        {
             throw;
        }
        catch (Exception ex)
        {
             throw new FooException("Inner Exception", ex);
        }
    }
}

so in summary you need to play with Inner Exception

helpfull links :

Throwing Custom Exception Best Practices

Is there a difference between “throw” and “throw ex”?

Best Practices for Exceptions

Throw exception but persist stack trace

Community
  • 1
  • 1
Sebastian 506563
  • 6,980
  • 3
  • 31
  • 56
  • I do just that in most cases, but reflection can throw so many different exceptions that it wouldn't make sense to try to catch them all with if's, because there are many different datatypes that I have to convert from string to date, integer, smallint, ... not to mention that there are x different exceptions that could occur in x different expressions.. Well thanks for all the Information. I think I'll use the dirty workaround for now ,though. – brocrow Feb 29 '16 at 12:14