gpt4 book ai didi

c# - StackFrame 在 Release模式下表现不同

转载 作者:可可西里 更新时间:2023-11-01 09:05:21 35 4
gpt4 key购买 nike

这是我的代码:

public class UserPreferences
{
/// <summary>
/// The EMail signature.
/// </summary>
[UserPreferenceProperty(Category = "Email", DefaultValue = "My default value")]
public static string Signature
{
get
{
return UserPreferenceManager.GetValue();
}

set
{
UserPreferenceManager.SetValue(value);
}
}
}

public static string GetValue()
{
if (((VTXPrincipal)Thread.CurrentPrincipal).VTXIdentity.OperatorID == null)
{
throw new Exception("Missing Operator ID");
}

string value = string.Empty;

var frame = new StackFrame(1); ***** <------ problem here.....

var property = frame.GetMethod();
var propertyname = property.Name.Split('_')[1];
var type = property.DeclaringType; ***** <------ problem here.....
if (type != null)
{
var userPreference = typeof(UserPreferences).GetProperty(propertyname).GetCustomAttributes(true).FirstOrDefault() as UserPreferencePropertyAttribute;

if (userPreference != null)
{
string category = userPreference.Category;
string description = propertyname;
value = GetValue(category, description, ((VTXPrincipal)Thread.CurrentPrincipal).VTXIdentity.OperatorID);
if (value == null)
{
// always return something
return userPreference.DefaultValue;
}
}
else
{
throw new Exception("Missing User Preference");
}
}

return value;
}

在 GetValue 方法内部,StackFrame 在 Release模式和 Debug模式下的工作方式不同。

在 Debug模式下,我正确地得到了属性名作为签名

但在 Release 模式下,属性名称是 GetUserPreferenceValueTest 因为这是作为客户端进行调用的测试方法。

因此我的代码在 Debug模式下工作但在 Release模式下失败。

Q. How can I use StackFrame properly so it works in Debug vs. Release modes. 

Q. Is there any other way to get calling property name and related information at run time?

最佳答案

我回答过一次类似的问题,请read my answer here .

简而言之,这是一个非常糟糕的设计决策,因为您的方法是一个伪君子——它与不同的调用者进行不同的对话,但没有公开说明。您的 API 应该永远、永远依赖调用它的人。此外,由于 lambda、yield 等语言特性,编译器可能会以意想不到的方式中断堆栈跟踪。和 await , 所以即使这在 Release模式下工作,它肯定有一天会崩溃。

您实际上是在构建一个复杂的间接机制,而不是使用设计的语言特性来将信息传递给方法——方法参数

为什么要使用属性?你在别处读过吗?

如果你这样做了,而且你不想重复 "Email"两者都作为 GetValue 的参数调用和属性值,你可以考虑传递一个属性Expression<>GetValue ,这将提取属性。这类似于您的解决方案,但它是明确的:

[UserPreferenceProperty(Category = "Email", DefaultValue = "My default value")]
public string Signature
{
get { return GetValue (prefs => prefs.Signature); }
set { SetValue (prefs => prefs.Signature, value); }
}

This answer shows how to implement this.

我看到你正在检查 Thread.CurrentPrincipal在你的代码中。同样,这不是一个很好的做法,因为对于客户端代码来说,访问属性可能会导致异常并不显而易见。对于支持您的代码的人(相信我,your code may run for years in production, long after you move onto another project),这将是一场调试噩梦。

相反,您应该制作 VTXIdentity设置类构造函数的参数。这将确保调用代码知道您在此级别上实现安全性,并且根据定义知道从何处获取此 token 。此外,这允许您在知道有问题时立即抛出异常,而不是在访问某些属性时抛出异常。这将有助于维护者及早发现错误——就像编译错误比运行时错误更好一样。

最后,虽然这是一个有趣的练习,但有 plenty performant and tested solutions for storing and reading configuration in C# .为什么您认为需要重新发明轮子?

关于c# - StackFrame 在 Release模式下表现不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14077153/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com