【发布时间】:2009-02-17 16:32:38
【问题描述】:
所以我有一个旨在实现 INotifyPropertyChanged 的 PropertyBag 类。为了使此代码尽可能干净地工作并避免用户错误,我使用堆栈来获取属性名称。看,如果属性名称与实际属性不完全匹配,那么您将失败,我正在努力避免这种情况。
所以,这里是一个类的用法示例:
public class MyData : PropertyBag
{
public MyData()
{
Foo = -1;
}
public int Foo
{
get { return GetProperty<int>(); }
set { SetProperty(value); }
}
}
基础 PropertyBag 的重要代码在这里:
public abstract class PropertyBag : INotifyPropertyChanged
{
protected T GetProperty<T>()
{
string propertyName = PropertyName((new StackTrace()).GetFrame(1));
if (propertyName == null)
throw new ArgumentException("GetProperty must be called from a property");
return GetValue<T>(propertyName);
}
protected void SetProperty<T>(T value)
{
string propertyName = PropertyName((new StackTrace()).GetFrame(1));
if (propertyName == null)
throw new ArgumentException("SetProperty must be called from a property");
SetValue(propertyName, value);
}
private static string PropertyName(StackFrame frame)
{
if (frame == null) return null;
if (!frame.GetMethod().Name.StartsWith("get_") &&
!frame.GetMethod().Name.StartsWith("set_"))
return null;
return frame.GetMethod().Name.Substring(4);
}
}
既然您已经看到了我的代码,我可以告诉您问题...在某些情况下,在发布版本下,“MyData”构造函数中的“Foo”设置器似乎被优化为内联为 SetProperty(- 1)。不幸的是,这种内联优化使我的 SetProperty 方法失败,因为我不再从属性中调用它!失败。看来我不能以这种方式依赖 StackTrace。
任何人都可以
A:想出一个更好的方法来做到这一点,但仍然避免将“Foo”传递给 GetProperty 和 SetProperty?
B:想办法告诉编译器在这种情况下不要优化?
【问题讨论】:
-
我忘了说 - 不要使用字典来存储 - 因为您往往拥有少量属性,所以扫描平面列表实际上要快得多(分水岭大约有 120 个键)。
-
你可以把它们变成虚拟的......
标签: c# stack-trace