Reputation: 3272
I have a series of 'codes' that I want to refer to properties in my class. However, when I set the values of the dictionary, the properties aren't updated. An example below
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; }
And the calling code
foo.CodeMap["stat"] = 27;
/* foo.Status is not set to 27 */
Is there a way to do this in .NET. I believe the error occurs because the dictionary value isn't an ref value, but I'm not sure the best way to do this. I saw https://stackoverflow.com/a/10350484/450745 but that is kinda the opposite of what I want.
Upvotes: 3
Views: 11050
Reputation: 606
For future viewers, in simple cases its enough to use Func'<'T'>'.
public string TestProperty {get; set;}
public Dictionary<int, Func<string>> dictionary;
Constructor()
{
dictionary = new Dictionary<int, Func<string>>
{
{1, ()=>TestProperty }
}
}
And when use like this:
dictionary[1]() or dictionary[1].Invoke()
It returns the actual value of property at the moment.
Upvotes: 3
Reputation: 900
Another way is using ExpandoObject. This is sample with one way binding to dictionary:
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;
}
}
}
using:
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);
Upvotes: 0
Reputation: 7299
Your code doesn't work because you add the Key, "stat", to the Dictionary
with whatever value Status has when the assignment is made. When you update that Key's value later, it won't automatically update your property. You are adding the value of a property at a point in time to the Dictionary
, but not the property itself.
What you want to do isn't possible using a standard Dictionary
. You have a couple of options that don't seem terrible though.
Observable Dictionary
See this blog post and this stackoverflow thread.
The general idea is to write a class that inherits from IDictionary<TKey, TValue>
, INotifyCollectionChanged
, and INotifyPropertyChanged
.
This will give you some hooks that you can write event handlers for that could theoretically allow you to update some properties or whatever else you wanted to do.
Refactor your code
If you don't like the above, then you could refactor your code slightly.
Consider this:
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>();
}
}
Then you could make the same call:
Foo foo = new Foo();
foo.CodeMap["stat"] = 27;
Console.WriteLine(foo.Status.ToString()); // prints 27
Hopefully it's fairly obvious why this works. Now the property actually references the Dictionary
. Be aware that you can't add the initial values the same way as before, as you would get a KeyNotFoundException
when the getter tries to access that Key. I see this as a pretty small downside however.
Upvotes: 2
Reputation: 4893
Dictionary doesn't update the value of previous value property. When you stored foo.CodeMap["stat"] = 27;
the earlier value of the foo.CodeMap["stat"]
(which was the value of Status
) gets overwritten with 27
.
A position identified by a key ("stat" in your case) within a dictionary is a data-store, i.e. CodeMap["stat"]
is the storage location of your data, not the other way round. Anything you store in this location overwrites previous data.
You should elaborate on your the actual problem that you are trying to solve. Your question isn't clear enough for readers to deduce the actual need/problem.
Upvotes: 0
Reputation: 30688
I believe the error occurs because the dictionary value isn't an ref value,
No it is because you have not set foo.Status
. foo.CodeMap
and foo.Status
are different.
If you want to sync the values, you should do it manually. You can inherit from IDictionary<TKey,TValue>
and override the Add
method.
like
void Add(TKey key, TValue value)
{
if (key is string && key.Equals("stat"))
{
this.stat = (int)value;
}
}
Upvotes: 1