我有一系列'代码',我想引用我班级的属性。但是,当我设置字典的值时,属性不会更新。下面的例子
public Foo() {
this.CodeMap = new Dictionary<string, object>();
this.CodeMap.Add("stat", this.Status);
this.CodeMap.Add("ver", this.Version);
}
public int Status { get; set; }
public int Version { get; set; }
和调用代码
foo.CodeMap["stat"] = 27;
/* foo.Status is not set to 27 */
有没有办法在.NET中执行此操作。我相信错误的发生是因为字典值不是ref值,但我不确定这样做的最佳方法。我看到https://stackoverflow.com/a/10350484/450745,但这与我想要的相反。
答案 0 :(得分:1)
我认为发生错误是因为字典值不是ref值,
不,因为你没有设置foo.Status
。 foo.CodeMap
和foo.Status
不同。
如果要同步值,则应手动执行。您可以继承IDictionary<TKey,TValue>
并覆盖Add
方法。
喜欢
void Add(TKey key, TValue value)
{
if (key is string && key.Equals("stat"))
{
this.stat = (int)value;
}
}
答案 1 :(得分:1)
您的代码不起作用,因为您将{Key>“stat”添加到Dictionary
,其中包含分配时状态所具有的任何值。当您稍后更新该Key的值时,它不会自动更新您的属性。您正在将某个时间点的属性值添加到Dictionary
,而不是属性本身。
使用标准Dictionary
无法实现您的目标。你有几个看起来并不可怕的选择。
可观察词典
请参阅此blog post和此stackoverflow thread。
一般的想法是编写一个继承自IDictionary<TKey, TValue>
,INotifyCollectionChanged
和INotifyPropertyChanged
的类。
这将为您提供一些钩子,您可以编写事件处理程序,理论上可以让您更新某些属性或其他任何您想要做的事情。
重构您的代码
如果您不喜欢上述内容,那么您可以稍微重构一下代码。
考虑一下:
public class Foo
{
public Dictionary<string, object> CodeMap;
public int Status
{
get
{
int status;
if (int.TryParse(CodeMap["stat"].ToString(), out status))
{
return status;
}
else
{
throw new Exception("Status has a non-numeric value");
}
}
set
{
CodeMap["stat"] = value;
}
}
public Foo()
{
CodeMap = new Dictionary<string, object>();
}
}
然后你可以拨打同一个电话:
Foo foo = new Foo();
foo.CodeMap["stat"] = 27;
Console.WriteLine(foo.Status.ToString()); // prints 27
希望这很有效,为什么会有效。现在,该属性实际引用了Dictionary
。请注意,您无法像以前一样添加初始值,因为当getter尝试访问该Key时,您将获得KeyNotFoundException
。我认为这是一个相当小的缺点。
答案 2 :(得分:1)
对于未来的观众,在简单的情况下,它足以使用Func&#39;&#39;&gt;&#39;&#39;
。 public string TestProperty {get; set;}
public Dictionary<int, Func<string>> dictionary;
Constructor()
{
dictionary = new Dictionary<int, Func<string>>
{
{1, ()=>TestProperty }
}
}
当这样使用时:
dictionary[1]() or dictionary[1].Invoke()
此时它返回属性的实际值。
答案 3 :(得分:0)
Dictionary不会更新先前value属性的值。当您存储foo.CodeMap["stat"] = 27;
foo.CodeMap["stat"]
的早期值(Status
的值)被27
覆盖时。
字典中的密钥(在您的情况下为“stat”)标识的位置是数据存储,即CodeMap["stat"]
是数据的存储位置,而不是相反。您在此位置存储的任何内容都会覆盖以前的数据。
您应该详细说明您要解决的实际问题。您的问题不够明确,读者无法推断出实际需要/问题。
答案 4 :(得分:0)
另一种方法是使用ExpandoObject。 这是单向绑定到字典的示例:
public class Foo
{
public Foo()
{
Properties = new ExpandoObject();
Status = 0;
Version = 0;
}
public dynamic Properties { get; set; }
public IDictionary<string, object> CodeMap
{
get { return Properties; }
}
private int _status;
public int Status
{
get { return _status; }
set
{
_status = value;
Properties.stat = _status;
}
}
private int _version;
public int Version
{
get { return _version; }
set
{
_version = value;
Properties.ver = _version;
}
}
}
使用:
var foo = new Foo
{
Status = 1,
Version = 2
};
Console.WriteLine(foo.CodeMap["stat"]);
Console.WriteLine(foo.CodeMap["ver"]);
Console.WriteLine(foo.Properties.stat);
Console.WriteLine(foo.Properties.ver);