Click here to Skip to main content
14,740,685 members
Articles » Languages » C# » General
Technical Blog
Posted 4 May 2011

Tagged as


2 bookmarked

Duck Typing with LinFu & C# 4.0's Dynamic Keyword

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
4 May 2011LGPL3
LinFu.DynamicObject is flexible enough that it can let you build object instances at runtime and then 'strongly' duck type those object instances to any interface that matches the intended duck type.

The Lame Duck

When C# 4.0 came out with the dynamic keyword, I was pretty excited over the prospect of having Ruby-like features finally being baked in to the C# language itself, but as one of my Twitter followers and friends pointed out in one of their posts from a few years ago, C# 4.0 still lacks duck typing support, and the .NET BCL doesn't seem to have anything that could do something similar to the following code:

public interface ICanAdd
    int Add(int a, int b);

public class SomethingThatAdds
    private ICanAdd _adder;

    public SomethingThatAdds(ICanAdd adder)
        _adder = adder;

    public int FirstNumber { get; set; }

    public int SecondNumber { get; set; }

    public int AddNumbers()
        return _adder.Add(FirstNumber, SecondNumber);

There has to be some way to construct an object at runtime and map it to an ICanAdd interface, but the problem is that the current .NET Base Class Libraries don't seem to have a solution for this problem. As Dave Tchepak pointed out in his post, the following dynamic code will fail miserably at runtime:

public class Dynamic : DynamicObject
    Dictionary<String, object> members = new Dictionary<string, object>();
    public override bool TrySetMember(SetMemberBinder binder, object value)
        members[binder.Name] = value;
        return true;
    public override bool TryGetMember(GetMemberBinder binder, out object result)
        return members.TryGetValue(binder.Name, out result);

// ..and the test would look like:
public void CannotUseDynamicAdderForAnythingUseful()
    dynamic adder = new Dynamic();
    adder.Add = new Func<int, int, int>((first, second) => first + second);
    var somethingThatCanAdd = new SomethingThatAdds(adder); /* Fails here at runtime */
    somethingThatCanAdd.FirstNumber = 10;
    somethingThatCanAdd.SecondNumber = 20;
    Assert.That(somethingThatCanAdd.AddNumbers(), Is.EqualTo(30));

The problem is that the runtime isn't smart enough to figure out that there has to be a duck-typing cast to the ICanAdd interface in order to use the SomethingThatCanAdd class, and that's where LinFu's DynamicObject comes in handy.

If It Walks and Quacks like a Duck, Then It's All Good

LinFu.DynamicObject is flexible enough that it can let you build object instances at runtime and then 'strongly' duck type those object instances to any interface that matches the intended duck type. In this case, we need to find a way to build up something that can map to an ICanAdd interface instance so that it can be used by the SomethingThatAdds class:

public void CanCreateADynamicAdder()
    var adder = new DynamicObject();
    CustomDelegate addBody = delegate(object[] args)
        int a = (int)args[0];
        int b = (int)args[1];
        return a + b;

    // Map LinFu's DynamicObject to an ICanAdd interface
    var linfuDynamicObject = new DynamicObject(new object());
    var returnType = typeof(int);
    var parameterTypes = new Type[] { typeof(int), typeof(int) };
    linfuDynamicObject.AddMethod("Add", addBody, returnType, parameterTypes);

    // If it looks like a duck...

    // ...then it must be a duck, right?
    var somethingThatCanAdd = new SomethingThatAdds(adder.CreateDuck<ICanAdd>());
    somethingThatCanAdd.FirstNumber = 10;
    somethingThatCanAdd.SecondNumber = 20;
    Assert.AreEqual(somethingThatCanAdd.AddNumbers(), 30);

The call to the DynamicObject.CreateDuck() method does all the heavy lifting for you so you don't have to worry about the details of how to make the object behave like a duck. It just works, and that's the power that LinFu offers.

(Edit: You can grab the source code and examples for LinFu.DynamicObject here at Github.)


This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


About the Author

Philip Laureano
Software Developer (Senior) Readify
Australia Australia
No Biography provided

Comments and Discussions

-- There are no messages in this forum --