Elton Stoneman

  Home  |   Contact  |   Syndication    |   Login
  82 Posts | 0 Stories | 115 Comments | 0 Trackbacks

News

Archives

Post Categories

[Source: http://geekswithblogs.net/EltonStoneman]

David Meyer has a neat duck typing library for .NET which I’ve been looking at as I had a requirement to treat objects of various types in the same way. They all expose a “Value” property, but don’t implement an interface.

The library does more than I needed so I put together a quick duck typing implementation which just lets me treat an instance of an object which tacitly implements an interface, as a true implementation of the interface. In this example I can access BespokeDateTime and BespokeInt as IHasValue:

Using Castle’s Dynamic Proxy, this is simple to do – just requiring you to generate an interface proxy with a custom interceptor. The interceptor invokes the interface method on the real object, so you effectively wrap an instance in an interface it doesn’t explicitly implement:

    BespokeDateTime bespoke = new BespokeDateTime(new DateTime(2000, 1, 1));

    IHasValue duck = DuckType.As<IHasValue>(bespoke);

    Console.WriteLine(duck.Value);

- or using an object extension to hide the implementation:

    bespoke.As<IHasValue>().Value;

Iterating over collections is much cleaner with duck typing – if I have a collection that contains both BespokeDateTime and BespokeInt objects, to get all their values I can use:

    foreach (object obj in GetObjects())

    {

        Assert.IsNotNull(DuckType.As<IHasValue>(obj).Value);

    }

- compared to casting each object:

    foreach (object obj in GetObjects())

    {

        BespokeDateTime bespokeDateTime = obj as BespokeDateTime;

        if (bespokeDateTime != null)

        {

            Assert.IsNotNull(bespokeDateTime.Value);

        }

        else

        {

            BespokeInt bespokeInt = (BespokeInt) obj;

            Assert.IsNotNull(bespokeInt.Value);

        }

    }

Use with caution over large collections, as there is a noticeable performance hit in using the duck type. Over 500,000 items the duck-typed code takes 40-50 times as long as the casting code, averaging 8 seconds to 0.2 seconds, with duck-typing by extension taking marginally longer again:

 


 

The full code (all 34 lines – including validation that the type to duck does tacitly implement the interface) is on MSDN Code Gallery here: Duck Typing with Castle.

 

posted on Wednesday, October 21, 2009 2:59 AM

Feedback

# re: Duck Typing with Castle 10/24/2009 3:49 PM Damon Wilder Carr
Brilliant. I ported to Silverlight 3 if anyone wants the bits. These bits of insight that are simple but deeply insightful are what I love most in our work as software craftsman. Fantastic insight into much more than just 'an API' is obvious in this, and your implementation shows you go deep and wide in both.

Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: