Pass the class name/method name in argument, possible? - c#

I've made a method that logs an exception into a folder called Logs and save it in the text file. The format of the text output is like so:
Main thread has thrown an exception # ClassName::MethodName : Exception.ToString();
ClassName::MethodName is a text that should contain which class and which method throws it (while doing the task). How is it possible to pass those arguments? For example, if I have a class named "Test", and I have this method:
public void DoSomething() {
try {
this.Name = "Test";
} catch (Exception e) {
MainForm.Instance.LogException(e);
}
Then if an exception was thrown, the arguments Test::DoSomething will be passed and shown. How is it possible to do it in C#?

You could use Reflection..
public void DoSomething() {
try {
this.Name = "Test";
} catch (Exception e) {
var method = System.Reflection.MethodBase.GetCurrentMethod();
var methodName = method.Name;
var className = method.ReflectedType.Name;
MainForm.Instance.LogException(String.Format("{0} - {1}:{2}", className, methodName, e));
}

The exception has a StackTrace property which gives you as much information as possible as to where the exception was thrown.

You can use the code below:
public static void DoSomething()
{
try
{
throw new InvalidOperationException("Exception");
}
catch (Exception e)
{
StackTrace stackTrace = new StackTrace();
StackFrame stackFrame = stackTrace.GetFrame(0);
Console.WriteLine("Class Name: {0}, Method Name: {1}", stackFrame.GetMethod().Module, stackFrame.GetMethod().Name);
}
}

e.StackTrace.GetFrame(0) will give you the most recent StackFrame.
Given that, e.StackTrace.GetFrame(0).GetMethod() will give you an instance of MethodBase, from this instance, you can get the method name and class

Related

C# Try Catch Statement Query

I have a question about Try Catch statements in C#.
For example if I had a statement as such
try
{
string text = sometext;
var Auto_IMPORT = new AutoImport();
Auto_IMPORT.StartProcessing();
Console.WriteLine(sometext);
}
catch(Exception Ex)
{
//Would this catch AutoImport.StartProcessing() exceptions?
Console.WriteLine(ex.Message);
}
AutoImport is a Class Library and i'm calling some logic to start processing.
If an exception occurred within the logic inside AutoImport.StartProcessing() would this try statement catch that exception or would it be out of scope by then?
Thanks In Advance
It depends on the behavior of Auto_IMPORT.StartProcessing(). If no exception is caught in it, then yes, you will get an exception. On the other hand, if the internal code off Auto_IMPORT catches the exception, and doesn't throw a new exception, then you wont get any exceptions.
Yes.
It catches any errors that are in the try block. Doesn't matter if they're in some method of some class.
Tested with:
class _Class
{
public string name;
public void myMethod()
{
int i;
string s = "asda";
i = int.Parse(s);
}
}
class Program
{
static void Main(string[] args)
{
try
{
_Class blah = new _Class();
blah.name = "Steve";
blah.myMethod();
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
Console.ReadLine();
}
Caught exception at int.Parse

How to remove try...catch block from many different functions [duplicate]

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.

Preserving exceptions from dynamically invoked methods

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");
}

Find Invoker Method Name

I have a structure like below:
public class BaseClass
{
public string SendError(string Message){
//which method called me
return Message;
}
}
public class TypeAClass : BaseClass
{
public static TypeAClass Instance { get; set;}
public void TestToTest()
{
SendError("Test Message");
}
}
Can I get the method name that calls the SendError() in the SendError method. For example, in this scenario it should give me the name TestToTest()
This is a feature of C# 5:
You can declare a parameter of a function as a caller info:
public string SendError(string Message, [CallerMemberName] string callerName = "")
{
Console.WriteLine(callerName + "called me.");
}
Try this
StackTrace stackTrace = new StackTrace();
String callingMethodName = stackTrace.GetFrame(1).GetMethod().Name;
StackFrame caller = (new System.Diagnostics.StackTrace()).GetFrame(0);
string methodName = caller.GetMethod().Name;
From the answer of the duplicate question:
using System.Diagnostics;
// get call stack
StackTrace stackTrace = new StackTrace();
// get calling method name
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
Or more brief:
new StackTrace().GetFrame(1).GetMethod().Name

How to get a value through a out/ref parameter from a method which throws an exception?

this code outputs "out value".
class P
{
public static void Main()
{
string arg = null;
try
{
Method(out arg);
}
catch
{
}
Console.WriteLine(arg);
}
public static void Method(out string arg)
{
arg = "out value";
throw new Exception();
}
}
but this one doesn't.
class P
{
public static void Main()
{
object[] args = new object[1];
MethodInfo mi = typeof(P).GetMethod("Method");
try
{
mi.Invoke(null, args);
}
catch
{
}
Console.WriteLine(args[0]);
}
public static void Method(out string arg)
{
arg = "out value";
throw new Exception();
}
}
how can I get both "out value" and an exception when using reflection?
The exception bypassed the code in MethodInfo.Invoke() that copies the [out] value from the stack frame back into the object array. The value on the stack frame that Invoke() created behaves just like it does in your 1st snippet. But that's where the similarities end.
The only way is to overload your method in a manner that accounts for the possibility of an exception and then pass one in "just in case". The following produces what I think you're looking for. The problem as I understand it is that reflection does not perform direct manipulation of the addresses passed in by reference. The addresses are not affected until the method end point is reached without exception. Possibly a memory protection or memory security scheme from MS.
class P
{
public static void Main()
{
object[] args = { "1", new Exception()};
MethodInfo mi = typeof(P).GetMethod("Method");
try
{
mi.Invoke(null, args);
}
catch
{
}
Console.WriteLine(args[0].ToString());
Console.WriteLine(args[1].ToString());
}
public static void Method(ref string arg, ref Exception ex)
{
try
{
arg = "out value";
throw new Exception();
}
catch (Exception exc)
{
ex = exc;
}
}
}
I would propose to change the method to return Result object instead of out parameter.
Result object can contain exception and also the value of your arg.
If the issue is, how do you catch that an exception has occured and you're working with a Windows Forms application, have you tried looking at the Thread Exception Event and combining it with the SetUnhandledExceptionMode()?
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
HandleException(e.Exception);
}
The out parameter is undefined if the method throws an exception. You can see this by not initialising it to null in the first example, then the code won't compile.
So, it makes sense for the Invoke method not to return the undefined value if the method throws an exception.

Categories