在C#中,有Exception
类。出于测试目的,我希望能够将其StackTrace
属性设置为任意字符串。 StackTrace
没有制定者,所以我的第一次尝试是尝试使用反射:
Exception instance = new Exception("Testing");
PropertyInfo propertyInfo = typeof(Exception).GetProperty("StackTrace");
propertyInfo.SetValue(instance, "Sample StackTrace value", null);
这会产生运行时错误:
System.ArgumentException : Property set method not found.
有什么办法可以设置StackTrace
属性吗?更一般地说,有没有办法设置一个缺少setter的属性?
答案 0 :(得分:10)
您可以派生自己的异常类并覆盖StackTrace
属性,即虚拟:
public sealed class MyException: Exception
{
public MyException(string message, string stackTrace): base(message)
{
_stackTrace = stackTrace;
}
public override string StackTrace
{
get
{
return _stackTrace;
}
}
private readonly string _stackTrace;
}
请注意,要正确执行此操作,您应该真正实现所有标准异常构造函数,但对于单元测试,这可能不是绝对必要的。
有关详细信息,请参阅Designing Custom Exceptions:
答案 1 :(得分:2)
该属性以这种方式实现:
public virtual string StackTrace
{
[__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
get
{
return this.GetStackTrace(true);
}
}
这种被调用的方法是这样实现的:
private string GetStackTrace(bool needFileInfo)
{
string text = this._stackTraceString;
string text2 = this._remoteStackTraceString;
if (!needFileInfo)
{
text = this.StripFileInfo(text, false);
text2 = this.StripFileInfo(text2, true);
}
if (text != null)
{
return text2 + text;
}
if (this._stackTrace == null)
{
return text2;
}
string stackTrace = Environment.GetStackTrace(this, needFileInfo);
return text2 + stackTrace;
}
因此,如果您将字段_stackTraceString
设置为任何String
,您将获得_stackTraceString
+ _remoteStackTraceString
。
您可以使用FieldInfo.SetValue设置字段。
我使用http://ilspy.net获取此信息。
不要在生产中执行此操作。由于某种原因,事物是以特定方式设计的,只是保证了公开的API,次要升级可能会更改此内部实现细节并破坏您的代码,因此永远不要依赖内部细节,只需暴露API。
干杯。
答案 2 :(得分:1)
您可以修改对象的支持字段:
Exception instance = new Exception("Testing");
var f = typeof(Exception).GetField("_stackTraceString", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
f.SetValue(instance, "hello");
这应该有效,以获取您可以使用的私人字段列表:
var fields = typeof(Exception).GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
我个人更喜欢Matthew Watson提出的解决方案。
答案 3 :(得分:0)
Exception对象的StackTrace属性由堆栈遍历期间的运行时设置,因此我们无法手动设置它。