Reputation: 26381
I have a use-case where I would need to add properties to a dynamic object in C# on reading, as opposed to writing. I.e. something like this:
class Foo : DynamicObject
{
private readonly Dictionary<string, object> _properties = new Dictionary<string, object>();
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (!_properties.TryGetValue(binder.Name, out result)
{
result = object();
_properties.Add(binder.Name, result);
}
return true;
}
}
class Test
{
public void Bar()
{
var o = new Foo();
// Fails!
var prop = o.SomeProperty;
}
}
The end-goal is to use this shim in LINQ expressions. I don't actually care for the value that is returned, all I want is for a convenient way to record the fact that the property has been accessed and then use that later when inspecting the expression tree.
Is this even possible with C#?
Upvotes: 1
Views: 495
Reputation: 918
I don't actually see trouble here. Tried it and result is quite as expected: Just added Properties property to get actual dictionary;
class Foo : DynamicObject {
private readonly Dictionary<string, object> _properties = new Dictionary<string, object>();
public Dictionary<string, object> Properties {
get { return _properties; }
}
public override bool TryGetMember(GetMemberBinder binder, out object result) {
if (!_properties.TryGetValue(binder.Name, out result)) {
result = new object();
_properties.Add(binder.Name, result);
}
return true;
}
}
now usage:
dynamic o = new Foo();
var prop = o.SomeProperty;
var prop2 = o.SomeNewProperty;
var allAccessedPropNames = o.Properties.Keys;
And allAccessedPropNames will result as {"SomeProperty", "SomeNewProperty"}
If you remove Add line from TryGetMember then it results with empty collection.
Upvotes: 2