如何Message
在C#中更改Exception对象?
该Message
属性Exception
是只读的:
public virtual string Message { get; }
Run Code Online (Sandbox Code Playgroud)
在PHP中,同样的问题被回答为"你不能",但是给出了一个解决方法:
但是,您可以确定它的类名和代码,并使用相同的代码但使用不同的消息抛出同一类的新类.
如何确定异常的类名,并在C#中使用不同的消息抛出同一个类的新类?
例如:
catch (Exception e)
{
Exception e2 = Activator.CreateInstance(e.GetType());
throw e2;
}
Run Code Online (Sandbox Code Playgroud)
不起作用,因为Message
异常的属性是只读的和.NET.见原始问题.
更新
我尝试捕获我期望的每种类型的异常:
try
{
reader.Read();
}
catch (OleDbException e)
{
throw new OleDbException(e, sql);
}
catch (SqlException e)
{
throw new SqlException (e, sql);
}
catch (IBM.DbException e)
{
throw new IBM.DbException(e, sql);
}
catch (OdbcException e)
{
throw new OdbcException (e, sql);
}
catch (OracleException e)
{
throw new OracleException (e, sql);
}
Run Code Online (Sandbox Code Playgroud)
除了现在我的代码强制依赖于不会出现在每个解决方案中的程序集.
此外,现在异常似乎来自我的代码,而不是抛出它的行; 我丢失了例外的位置信息
Ric*_*ard 30
您创建一个Exception
具有新消息的新(或更好的特定子类型)(并将原始异常作为传递InnerException
).
例如.
throw new MyExceptionType("Some interesting message", originalException);
Run Code Online (Sandbox Code Playgroud)
NB.如果你真的想要使用,Activator.CreateInstance
你可以使用可以传递参数的重载,但是不能依赖不同的Exception派生类型来为构造函数重载(message, innerException)
.
Ian*_*oyd 17
catch (Exception e)
{
Exception e2 = (Exception)Activator.CreateInstance(e.GetType(), message, e);
throw e2;
}
Run Code Online (Sandbox Code Playgroud)
它并不完美(你丢失了堆栈跟踪); 但这就是.NET的本质.
您可以通过反射更改异常消息,如下所示......
Exception exception = new Exception("Some message.");
var type = typeof(Exception);
var flags = BindingFlags.Instance | BindingFlags.NonPublic;
var fieldInfo = type.GetField("_message", flags);
fieldInfo.SetValue(exception, message);
Run Code Online (Sandbox Code Playgroud)
所以你可以创建一个扩展方法......
namespace ExceptionExample
{
public static class ExceptionExtensions
{
public static void SetMessage(this Exception exception, string message)
{
if (exception == null)
throw new ArgumentNullException(nameof(exception));
var type = typeof(Exception);
var flags = BindingFlags.Instance | BindingFlags.NonPublic;
var fieldInfo = type.GetField("_message", flags);
fieldInfo.SetValue(exception, message);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后用它...
...
using static ExceptionExample.ExceptionExtensions;
public class SomeClass
{
public void SomeMethod()
{
var reader = AnotherClass.GetReader();
try
{
reader.Read();
}
catch (Exception ex)
{
var connection = reader?.Connection;
ex.SetMessage($"The exception message was replaced.\n\nOriginal message: {ex.Message}\n\nDatabase: {connection?.Database}");
throw; // you will not lose the stack trace
}
}
}
Run Code Online (Sandbox Code Playgroud)
你必须记住,如果你使用“throw ex;” 堆栈跟踪将会丢失。
为了避免这种情况,你必须使用“throw;” 无一例外。
我只是想在这里与Ian相关的答案.如果您在博客文章中使用该技术,您将不会丢失堆栈.是的,您将丢失StackTrace
最终异常成员中的堆栈,但由于内部异常,您不会丢失整个堆栈.看这里:
class Program
{
static void Main(string[] args)
{
try
{
Test1();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
public static void Test1()
{
try
{
Test2();
}
catch (Exception ex)
{
throw ExceptionUtil.Rethrow(ex, "caught in test1");
}
}
public static void Test2()
{
throw new Exception("test2");
}
public static class ExceptionUtil
{
public static Exception Rethrow(Exception ex, string message)
{
if (ex == null)
{
ex = new Exception("Error rethrowing exception because original exception is <null>.");
}
Exception rethrow;
try
{
rethrow = (Exception)Activator.CreateInstance(ex.GetType(), message, ex);
}
catch (Exception)
{
rethrow = new Exception(message, ex);
}
return rethrow;
}
public static Exception Rethrow(Exception ex, string message, params object[] args)
{
string formatted;
try
{
formatted = String.Format(message, args);
}
catch (Exception ex2)
{
formatted = message + "\r\n\r\nAn error occurred filling in exception message details:\r\n\r\n" + ex2;
}
return Rethrow(ex, formatted);
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您获取异常的完整字符串,您将获得:
System.Exception: caught in test1 ---> System.Exception: test2
at ScratchPad2.Program.Test2() in C:\Projects\Experiments\ScratchPad2\Program.cs:line 36
at ScratchPad2.Program.Test1() in C:\Projects\Experiments\ScratchPad2\Program.cs:line 26
--- End of inner exception stack trace ---
at ScratchPad2.Program.Test1() in C:\Projects\Experiments\ScratchPad2\Program.cs:line 30
at ScratchPad2.Program.Main(String[] args) in C:\Projects\Experiments\ScratchPad2\Program.cs:line 14
Run Code Online (Sandbox Code Playgroud)
所以你无论如何都得到了整个堆栈,还有额外的信息
您可以使用新消息将先前的异常包装在一个新的异常中,并使用堆栈跟踪/等的内部异常。
try
{
throw new Exception("This error message sucks");
}
catch (Exception e)
{
throw new Exception("There error message is prettier", e);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
33062 次 |
最近记录: |