C# 如何从其构造函数设置自定义异常类的 InnerException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1466800/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set the InnerException of custom Exception class from its constructor
提问by
How can I set the InnerException
property of an Exception
object, while I'm in the constructor of that object? This boils down to finding and setting the backing field of a property that has no setter.
当我在该对象的构造函数中时,如何设置该对象的InnerException
属性Exception
?这归结为查找和设置没有 setter 的属性的支持字段。
BTW: I have seen this evain.net - Getting the field backing a property using Reflectionbut looking for non IL-based solution, if possible.
顺便说一句:我见过这个evain.net - 使用反射获取支持属性的字段,但如果可能的话,寻找非基于 IL 的解决方案。
The constructor of Exception
is the place where the Exception
type is created, so I cannot call it using the base class constructor MyException() :base(...)
etc.
的构造函数是创建类型Exception
的地方Exception
,所以我不能使用基类构造函数MyException() :base(...)
等调用它。
采纳答案by Meta-Knight
Why can't you just call the constructor taking the InnerException as a parameter? If for some reason it's not possible, the backing field in System.Exception is:
为什么不能只调用以 InnerException 作为参数的构造函数?如果由于某种原因不可能,System.Exception 中的支持字段是:
private Exception _innerException;
I found it out using Redgate's Reflector. Using reflection I suppose you could set the inner exception.
我使用Redgate 的 Reflector发现了它。使用反射我想你可以设置内部异常。
Edit:In most cases it's not a good idea to access private fields via reflection, but I don't know enough about NT's case to know for sure if it's a good or bad idea.
编辑:在大多数情况下,通过反射访问私有字段不是一个好主意,但我对 NT 的情况了解得不够,无法确定这是一个好主意还是坏主意。
回答by dove
Exception exceptionWithMoreInfo = new Exception("extra info", ex);
would be normal practice assuming you've trapped an exception to which you'd like to add more information before bubbling up.
假设您已经陷入了一个异常,您想在冒泡之前添加更多信息,这将是正常的做法。
回答by Marc Gravell
You set the inner exception by calling the base ctor:
您可以通过调用基本构造函数来设置内部异常:
public MyException(string message, Exception innerException)
: base(message, innerException) {...}
If you need to run some code to get the exception, use a static method:
如果您需要运行一些代码来获取异常,请使用静态方法:
public MyException(SomeData data) : base(GetMessage(data), GetInner(data)) {...}
static Exception GetInner(SomeData data) {...} // <===== your type creation here!
static string GetMessage(SomeData data) {...}
回答by Joey
Isn't InnerException
supposed to be set when using the Exception(string, Exception)
constructor? I think it's by design that you can't change this otherwise but you can always defer to the appropriate constructor at construction time:
InnerException
使用Exception(string, Exception)
构造函数时不应该设置吗?我认为这是设计使然,否则您无法更改此设置,但您始终可以在构建时遵循适当的构造函数:
class MyException : Exception {
public MyException()
: base("foo", new Exception("bar"))
{
...
}
...
}
I think you shouldn't ever break the exception chain in your code since that usually leads to errors you will never find again.
我认为您永远不应该破坏代码中的异常链,因为这通常会导致您再也找不到的错误。
回答by Paolo Tedesco
The Exception
class has an overloaded constructor accepting the inner exception as a parameter:
的Exception
类有一个重载的构造接受的内部异常作为参数:
Exception exc = new Exception("message", new Exception("inner message"));
Is this what you are looking for?
这是你想要的?
回答by pauloya
If I understand your question you want to do something like this:
如果我理解你的问题,你想做这样的事情:
Exception ex = new Exception("test");
Exception innerEx = new Exception("inner");
ex.GetType().GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(ex, innerEx);
If you are in the constructor of an object that inherits from Exception you would use this
instead of the first ex
.
如果您在从 Exception 继承的对象的构造函数中,您将使用this
而不是第一个ex
.
But this may not be the best way to handle whatever it is you are trying to handle.
但这可能不是处理您试图处理的任何事情的最佳方式。
回答by NT_
Use Redgate's Reflector to find the field. I doubt the Exception implementation will ever change... But it is a risk!
使用 Redgate 的 Reflector 找到该字段。我怀疑 Exception 实现会永远改变......但这是一个风险!
回答by NT_
I know I'm really late to the party, but I find that this works.
我知道我参加聚会真的很晚,但我发现这很有效。
public class MyException: Exception
{
public void SetInnerException(Exception exception)
{
typeof(Exception)
.GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(this, exception);
}
}
The trick is to get the actual Exception
type's _innerException
field, and then set the inner exception value to your class instance (MyException
in this case).
诀窍是获取实际Exception
类型的_innerException
字段,然后将内部异常值设置为您的类实例(MyException
在本例中)。
This also works for variables.
这也适用于变量。
Exception mainException = new Exception();
typeof(Exception)
.GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(mainException , new Exception("Something bad happened!"));
回答by shA.t
In my situation I used this code:
在我的情况下,我使用了以下代码:
class Foo
{
void Bar(MyException myException = null)
{
try
{
SomeActions.Invoke();
}
catch (Exception ex)
{
if (myException != null)
{
// Here I regenerate my exception with a new InnerException
var regenMyException = (MyException)System.Activator.CreateInstance(myException.GetType(), myException.Message, ex);
throw regenMyException;
}
throw new FooBarException("Exception on Foo.Bar()", ex);
}
}
}
HTH someone ;).
HTH某人;)。