I want to be able to access property values in an object like a dictionary, using the name of the property as a key. I don\'t really care if the values are returned as objec
I don't believe there is a built-in .Net type like this already in the .Net framework. It seems like you really want to create an object that behaves a lot like a Javascript object. If so then deriving from DynamicObject
may be the right choice. It allows you to create an object which when wrapped with dynamic
allows you to bind directly obj.Name
or via the indexer obj["Name"]
.
public class PropertyBag : DynamicObject {
private object _source;
public PropertyBag(object source) {
_source = source;
}
public object GetProperty(string name) {
var type = _source.GetType();
var property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
return property.GetValue(_source, null);
}
public override bool TryGetMember(GetMemberBinder binder, out object result) {
result = GetProperty(binder.Name);
return true;
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) {
result = GetProperty((string)indexes[0]);
return true;
}
}
You can use this to wrap any type and use both the indexer and name syntax to get the properties
var student = new Student() { FirstName = "John", LastName = "Doe" };
dynamic bag = new PropertyBag(student);
Console.WriteLine(bag["FirstName"]); // Prints: John
Console.WriteLine(bag.FirstName); // Prints: John
dynamic keyword may be one option for you. it uses dynamic language runtime. At runtime, it tries to match the closest available type in the program. If it cant, then it converts the dynamic type to dictionay object, where key is the name of property and value is the value of property.
follow these links of MSDN:
Using dynamic keyword in C#
dynamic (C# Reference)
DLR Overview
usage of dynamic sample walkthough page
I have this extension method, probably the simplest it can get:
public static Dictionary<string, object> ToPropertyDictionary(this object obj)
{
var dictionary = new Dictionary<string, object>();
foreach (var propertyInfo in obj.GetType().GetProperties())
if (propertyInfo.CanRead && propertyInfo.GetIndexParameters().Length == 0)
dictionary[propertyInfo.Name] = propertyInfo.GetValue(obj, null);
return dictionary;
}
Now you can do:
object person = new { Name = "Bob", Age = 45 };
var lookup = person.ToPropertyDictionary();
string name = (string)lookup["Name"];
lookup["Age"] = (int)lookup["Age"] + 1; // indeed editable
Note:
that this dictionary is case-sensitive (you can trivially extend it passing the right StringComparer
).
that it ignores indexers (which are also properties) but it's up to you to work on it.
that the method is not generic considering it doesn't help boxing because internally it calls obj.GetType
, so it boxes anyway at that point.
that you get only the "readable" properties (otherwise you dont get the values held in it). Since you want it to be "writable" as well then you should use CanWrite
flag as well.