StackFrame在发布模式下表现不同
这是我的代码:
public class UserPreferences { /// /// The EMail signature. /// [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在发布模式与调试模式下的工作方式不同。
在调试模式下,我正确地将属性名称作为签名
但在发布模式下,属性名称为GetUserPreferenceValueTest,因为这是将调用作为客户端的测试方法。
因此,我的代码在调试模式下工作,但在发布模式下失败。
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?
我曾回答过一个类似的问题,请在这里阅读我的答案 。
简而言之,这是一个非常糟糕的设计决策,因为你的方法是一个伪君子 – 它与不同的调用者不同,但不会在开放时告诉它。 您的API 永远不应该依赖于谁调用它。 此外,由于lambda, yield
和await
类的语言function,编译器可以以意想不到的方式打破堆栈跟踪,所以即使这在Release模式下工作,它肯定会在某一天中断。
您正在有效地构建复杂的间接机制,而不是使用为将信息传递给方法 – 方法参数而设计的语言function。
为什么使用属性? 你在其他地方看过吗?
如果你这样做,并且你不想重复"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); } }
这个答案显示了如何实现这一点。
我看到你正在检查代码中的Thread.CurrentPrincipal
。 同样,这不是一个非常好的做法,因为对于客户端代码而言,访问属性可能导致exception并不明显 。 对于支持您的代码的人来说,这将是一个调试噩梦(并且相信我, 您的代码可能会在生产中运行多年,在您迁移到另一个项目之后很久 )。
相反,您应该将VTXIdentity
作为设置类构造函数的参数 。 这将确保调用代码知道您在此级别上强制执行安全性,并且根据定义知道在何处获取此令牌。 此外,这允许您在知道错误时立即抛出exception,而不是在访问某些属性时抛出exception。 这将有助于维护者更早地捕获错误 – 就像编译错误比运行时错误更好。
最后,虽然这是一个有趣的练习,但有很多高性能和经过测试的解决方案,用于在C#中存储和读取配置 。 为什么你认为你需要重新发明轮子?
假设你的问题仍然存在,你是否可以使用另一个库而不是滚动自己的问题……如果你发现自己使用的是C#5和.NET 4.5,请查看CallerMemberName属性。 使用CallerMemberName,您可以修改GetValue()方法签名
public static string GetValue([CallerMemberName] string callerName = "")
然后,该属性可以调用没有参数的GetValue(),并且您将根据需要将属性名称传递给GetValue()。
上述就是C#学习教程:StackFrame在发布模式下表现不同分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1269842.html