设置没有Setter的C#属性
在C#中,存在设置没有Setter的C#属性,c#,reflection,C#,Reflection,在C#中,存在异常类。出于测试目的,我希望能够将其StackTrace属性设置为任意字符串StackTrace没有setter,因此我的第一次尝试是尝试使用反射: Exception instance = new Exception("Testing"); PropertyInfo propertyInfo = typeof(Exception).GetProperty("StackTrace"); propertyInfo.SetValue(instance, "Sample StackTra
异常
类。出于测试目的,我希望能够将其StackTrace
属性设置为任意字符串StackTrace
没有setter,因此我的第一次尝试是尝试使用反射:
Exception instance = new Exception("Testing");
PropertyInfo propertyInfo = typeof(Exception).GetProperty("StackTrace");
propertyInfo.SetValue(instance, "Sample StackTrace value", null);
这将产生运行时错误:
System.ArgumentException:未找到属性集方法。
有没有办法设置
StackTrace
属性?一般来说,有没有办法设置缺少setter的属性?异常对象的StackTrace属性是在堆栈遍历期间由运行时设置的,因此我们无法手动设置它。您可以派生自己的异常类并重写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;
}
请注意,要正确地执行此操作,您应该真正实现所有标准异常构造函数,但对于单元测试来说,这可能不是严格必要的
有关更多详细信息,请参见:该属性是通过以下方式实现的:
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;
}
被调用的方法是这样实现的:
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;
}
因此,如果您将字段\u stackTraceString
设置为任何字符串
,您将获得\u stackTraceString
+\u remoteStackTraceString
可以使用设置字段
我是用电脑得到这个信息的
不要在生产中这样做。事情的设计是有原因的,只是公开的API是有保证的,轻微的升级可能会改变这个内部实现细节并破坏您的代码,所以永远不要依赖内部细节,只依赖公开的API
干杯。您可以修改对象的背景字段:
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提出的解决方案。您可以使用Reflector找出此属性调用的支持变量,然后使用reflection来设置。扩展您自己的异常类怎么样?@Nick-没有支持字段:
返回此。GetStackTrace(true)代码>实际上有一个支持字段@Nick在is断言中是正确的:\u stackTraceString
可通过反射进行设置。这是一个好的解决方案,但覆盖所有异常以使用自定义异常类是不可行的。也许您也可以编写一个包装异常类,仅用于测试目的。没错,在测试库中创建我自己的异常类(仅在该库内部)可能比反射更好。在C
中,对变量名使用\u paramName
是否正常。o@mmcrae这在私有字段中非常常见。但是,通过键入“\u paramName”你让它看起来像是在考虑参数名——这对那些人来说肯定不正常。我发布的代码将其用于私有字段,而不是参数。有些人使用这个。
代替,如果使用\u
则有理由将其用作后缀。