Dynamic objects part II

I decided to extend my DynamicObject class to enable me to do this:

[Test]
public void MyDynamicObject_SetWithSetter_CanGetByReference()
{
    // Arrange
    dynamic obj = new MyDynamicObject();
    obj["property1"] = true;

    // Act
    bool value = obj.property1;

    // Assert
    Assert.That(value);
}

And this:

[Test]
public void MyDynamicObject_SetDelegateWithSetter_CanCallDelegate()
{
    // Arrange
    dynamic obj = new MyDynamicObject();
    Func<bool> d = () => true;
    obj["property1"] = d;

    // Act
    bool value = obj.property1();

    // Assert
    Assert.That(value);
}

And this (something I hope to use with Entity Framework):

[Test]
public void MyDynamicObject_SetExpressionWithSetter_CanCallExpression()
{
    // Arrange
    dynamic obj = new MyDynamicObject();
    Expression<Func<bool>> d = () => true;
    obj["property1"] = d;

    // Act
    bool value = obj.property1.Compile()();

    // Assert
    Assert.That(value);
}

The update to the code requires adding the following indexed property:

public virtual object this[string key] 
{
    get
    {
        return this.dictionary[key];
    }
    set
    {
        this.dictionary[key] = value;
    }
}

When inheriting from this class it’s important to remember to store members in the underlying DynamicObject, e.g.

public class MyDynamicObject1 : AbstractDynamicObject
{
    public Func<bool> property1
    {
        get
        {
            return this["property1"] as Func<bool>;
        }
        set
        {
            this["property1"] = value;
        }
    }
}

Here’s the complete class for reference:

// http://www.abhisheksur.com/2010/07/dynamic-behaviour-on-objects-at-runtime.html
public abstract class AbstractDynamicObject : DynamicObject
{
    private IDictionary<string, object> dictionary { get; set; }

    public AbstractDynamicObject()
    {
        this.dictionary = new Dictionary<string, object>();
    }

    public int Count { get { return this.dictionary.Keys.Count; } }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (this.dictionary.ContainsKey(binder.Name))
        {
            result = this.dictionary[binder.Name];
            return true;
        }

        return base.TryGetMember(binder, out result); //means result = null and return = false
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        if (!this.dictionary.ContainsKey(binder.Name))
        {
            this.dictionary.Add(binder.Name, value);
        }
        else
        {
            this.dictionary[binder.Name] = value;
        }

        return true;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        if (this.dictionary.ContainsKey(binder.Name) && this.dictionary[binder.Name] is Delegate)
        {
            Delegate del = this.dictionary[binder.Name] as Delegate;
            result = del.DynamicInvoke(args);
            return true;
        }

        return base.TryInvokeMember(binder, args, out result);
    }

    public override bool TryDeleteMember(DeleteMemberBinder binder)
    {
        if (this.dictionary.ContainsKey(binder.Name))
        {
            this.dictionary.Remove(binder.Name);
            return true;
        }

        return base.TryDeleteMember(binder);
    }

    public override IEnumerable<string> GetDynamicMemberNames()
    {
        foreach (string name in this.dictionary.Keys)
        {
            yield return name;
        }
    }

    public virtual object this[string key] 
    {
        get
        {
            return this.dictionary[key];
        }
        set
        {
            this.dictionary[key] = value;
        }
    }
}