当我在该对象的构造函数中时,如何设置InnerException
对象的Exception
属性?这归结为查找和设置没有setter的属性的支持字段。
顺便说一句:我已经看过这个evain.net - Getting the field backing a property using Reflection但是如果可能的话,还要寻找非基于IL的解决方案。
Exception
的构造函数是创建Exception
类型的位置,因此我无法使用基类构造函数MyException() :base(...)
等来调用它。
答案 0 :(得分:76)
通过调用base ctor来设置内部异常:
public MyException(string message, Exception innerException)
: base(message, innerException) {...}
如果需要运行一些代码来获取异常,请使用静态方法:
public MyException(SomeData data) : base(GetMessage(data), GetInner(data)) {...}
static Exception GetInner(SomeData data) {...} // <===== your type creation here!
static string GetMessage(SomeData data) {...}
答案 1 :(得分:37)
Exception
类有一个重载的构造函数接受内部异常作为参数:
Exception exc = new Exception("message", new Exception("inner message"));
这是你在找什么?
答案 2 :(得分:13)
为什么不能只将内部异常作为参数调用构造函数?如果由于某种原因无法实现,System.Exception中的支持字段为:
private Exception _innerException;
我使用Redgate's Reflector找到了它。使用反射我想你可以设置内部异常。
编辑:在大多数情况下,通过反射访问私有字段并不是一个好主意,但我不太了解NT的情况,以确定它是好主意还是坏主意。< / p>
答案 3 :(得分:8)
Exception exceptionWithMoreInfo = new Exception("extra info", ex);
通常的做法是假设你已经陷入了一个例子,你想在冒泡之前添加更多信息。
答案 4 :(得分:2)
如果我理解你的问题,你想做这样的事情:
Exception ex = new Exception("test");
Exception innerEx = new Exception("inner");
ex.GetType().GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(ex, innerEx);
如果您在继承自Exception的对象的构造函数中,则使用this
而不是第一个ex
。
但这可能不是处理你想要处理的任何事情的最佳方法。
答案 5 :(得分:1)
使用InnerException
构造函数时是不是应该设置Exception(string, Exception)
?我认为按照设计你不能改变它,但你总是可以在施工时遵从相应的构造函数:
class MyException : Exception {
public MyException()
: base("foo", new Exception("bar"))
{
...
}
...
}
我认为您不应该破坏代码中的异常链,因为这通常会导致您再也找不到错误。
答案 6 :(得分:1)
使用Redgate的Reflector查找字段。我怀疑异常实现是否会改变......但这是一种风险!
答案 7 :(得分:0)
我知道我参加派对的时间已经很晚了,但我觉得这很有效。
public class MyException: Exception
{
public void SetInnerException(Exception exception)
{
typeof(Exception)
.GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(this, exception);
}
}
诀窍是获取实际的Exception
类型的_innerException
字段,然后将内部异常值设置为您的类实例(在这种情况下为MyException
)。< / p>
这也适用于变量。
Exception mainException = new Exception();
typeof(Exception)
.GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(mainException , new Exception("Something bad happened!"));
答案 8 :(得分:0)
在我的情况下,我使用了以下代码:
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);
}
}
}
有人;)。