Brian Ritchie's Blog

My ramblings on .NET & other development topics

News



Twitter

Blog Roll

Connect with me

DynamicDuck: Duck Typing in a Dynamic World

When dynamics came to C#, I hoped that we'd be able to use interfaces to bridge the gap between dynamic & static typing.

For example, the following really should just work:

    public interface IUser
{
string Username { get; set; }
}
static class Sample
{
public static void Main()
{
dynamic test = new ExpandoObject();
test.Username = "jsmith";
AddUser(test);
}
public static void AddUser(IUser user)
{
Console.WriteLine("Adding user {0}", user.Username);
}
}

It compiles just fine, but you get the following at runtime:

   Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:'The best overloaded method match for 'DynamicDuck.Sample.AddUser(DynamicDuck.IUser)' has some invalid arguments'

Well, this just makes me grumpy.  So either I'm missing something...which is always possible. (If so, please let me know!)  Or this just isn't possible in C# 4.0.  Working under the assumption that it isn't possible, I started looking into Duck Typing.  I wasn't able to find anyone who had created a Duck Type Library for dynamics, so I took the DuckTaper source and retrofitted it to work with dynamics.

So, when you apply the DynamicDuck this code works.

AddUser(DynamicDuck.AsIf<IUser>(test));

How does it work?  DynamicDuck creates a class that implements the interface and proxies the calls back to the dynamic object. The current duck typing code currently just handles properties, but could be enhanced to support methods in the future. 

This functionality works perfectly for DTOs and marshaling data between JSON, XML, or dynamic languages.

Hopefully, this will just be "included" with .NET in the future.  But until then...there is DynamicDuck!

[ Download the source ]

 

Comments

David Taylor said:

ExpandoObject is sealed too - so to implement something yourself letting you implement an interface would require you to inherit from DynamicObject.  You would have some work to do.

Is it possible to implement what you have done as an extension method, as:

AddUser(test.AsIf<IUser>());

would be more readable compared to:

AddUser(DynamicDuck.AsIf<IUser>(test));

In the first example kind of just reads that you are passing test "as if" it were an "IUser".

You should be able to implement as an extension method of ExpandoObject?

Regards,

Dave

# August 4, 2010 1:38 AM

brian_ritchie said:

Dave,

Using an extension method was my first idea too.  However, the runtime system didn't recognize the method.  I think the compiler didn't perform the normal extension method magic since it assumed this method was in the dynamic world.  To get extension methods to work, I had to cast the object first which made it less readable.

-Brian

# August 4, 2010 9:28 AM

MonoTools 2 Released, Dynamic Duck Typing, Twilio…. « Just Another Geek said:

Pingback from  MonoTools 2 Released, Dynamic Duck Typing, Twilio&#8230;. &laquo; Just Another Geek

# August 4, 2010 9:29 AM

Brian Ritchie's Blog said:

I've been working with RavenDB and Json.NET lately. RavenDB has some interesting schema-less capabilities

# August 5, 2010 11:02 PM

The Redeblog » Blog Archive » cast ExpandoObject to Interface in Silverlight said:

Pingback from  The Redeblog  &raquo; Blog Archive   &raquo; cast ExpandoObject to Interface in Silverlight

# August 19, 2010 5:17 PM

DalSoft said:

Clay is a dynamic C# type that allows casting to a static type. It's great I've used it in project recently.

http://clay.codeplex.com/

# January 16, 2011 5:56 PM

Lars Stenberg said:

Just some suggestions to the DynamicDuck generate get method IL.

methodIlGen.Emit(OpCodes.Ldarg_0);

methodIlGen.Emit(OpCodes.Ldstr, methodName);

*methodIlGen.Emit(OpCodes.Ldtoken, propertyBuilder.PropertyType);

methodIlGen.Emit(OpCodes.Call, GetPropertyMethod);

*methodIlGen.Emit(OpCodes.Unbox_Any, propertyBuilder.PropertyType);

methodIlGen.Emit(OpCodes.Ret);

Added the target type to the call so we can make special case handing in the base class.

Unbox returned value to handle value types (as ints) proberly.

Removed the local variable, the returned value got pushed to the evaluation stack so we can simply return it.

Thanks for a great example.

/L

# January 25, 2011 4:18 AM

DalSoft said:

Just an update to my previous comment and to let you know that I swapped Clay out for your code. Reason - your code can be Serialized easily with JsonConvert.SerializeObject. I think this is because your code works with the ExpandoObject and Clay works with a Castle Proxy. I probably could of got Clay working, but your code worked first time and did what I wanted mainly casting a dynamic to a interface.

So thanks again for a great post and thank you to Lars for his comment above that fixes the problem with returning value types.

# January 26, 2011 5:49 AM

Jay Tuley said:

Hi Brian, I thought you might be interested, I've released a opensource framework that does Duck Casting fully for dynamic objects. It handles every case I can think of methods an property declarations on an interface including generics and out variables (unit tests for everything). Also it should handle any dynamic object even, even if they don't inherit from DynamicObject plus handles regular classes and anonymous classes (even across assembly boundaries).

it's called ImpromptuInterface since you are someone who has written an implementation and also has a need. I would be happy to get any feedback.

code.google.com/.../impromptu-interface

Thanks!

# March 1, 2011 7:42 PM

Healer said:

It's cool, but can not resolve my problem. The code depends on Emit classes. But Win8 Store apps do not support this namespace...

# November 20, 2012 3:20 AM

genfaviocn.com said:

By WebOsPublisher

Phillip Haydon &raquo; Hide $ Show Buttons with Sencha Touch

@import url( philliphaydon.com/wp-content/themes/inove/style.css );

Phillip Haydon

Works on my pc.

Home

Home

&gt; Sencha Touch &gt; Hide $ Show Buttons with Sencha Touch

Hide $ Show Buttons with Sencha Touch

June 12th, 2011

Phillip

I’m currently building a demo for work using Sencha Touch mobile JavaScript framework, and needed to change the state of some buttons dependent on which ‘card’ is shown.

The Doc Api is a little hard to follow in my opinion, but I eventually worked it out.

In hindsight I guess I could have used a single button to do this, but I will demonstrate it with two.

To demonstrate this I’m going to use a Panel, with the buttons to flick between the cards. Instead of using a TabPanel.

So to start with I have a Panel, with a ToolBar docked to the bottom, a couple of buttons, and two cards.

var rootPanel;

Ext.setup( В В В В onReady: function ()  В В В В В В В В rootPanel = new Ext.Panel( В В В В В В В В В В В В fullscreen: true, В В В В В В В В В В В В layout: 'card', В В В В В В В В В В В В style: 'background-color:lightblue;', В В В В В В В В В В В В dockedItems: <>В В В В В В В В В В В В В В В В  В В В В В В В В В В В В В В В В В В В В dock: 'bottom', В В В В В В В В В В В В В В В В В В В В xtype: 'toolbar', В В В В В В В В В В В В В В В В В В В В items: <>В В В В В В В В В В В В В В В В В В В В В В В В  В В В В В В В В В В В В В В В В В В В В В В В В В В В В html: 'Card 1 Button' В В В В В В В В В В В В В В В В В В В В В В В В , В В В В В В В В В В В В В В В В В В В В В В В В  В В В В В В В В В В В В В В В В В В В В В В В В В В В В docked: 'right', В В В В В В В В В В В В В В В В В В В В В В В В В В В В html: 'Card 2 Button' В В В В В В В В В В В В В В В В В В В В В В В В  В В В В В В В В В В В В В В В В В В В В ] В В В В В В В В В В В В В В В В  В В В В В В В В В В В В ], В В В В В В В В В В В В items: <>html: 'card 1' ,  html: 'card 2' ] В В В В В В В В ); В В В В  );

 

At the moment it’s all nested, so the first thing I’ll do is pull the toolbar items out, I’ll also assign them to local variables and create them using the Ext.Button type. This gives us access to the methods and events for the buttons.

var btnCardOne = new Ext.Button( В В В В html: 'Card 1 Button' );

var btnCardTwo = new Ext.Button( В В В В docked: 'right', В В В В hidden: true, В В В В html: 'Card 2 Button' );

items: <btnCardOne> btnCardTwo]

 

You will notice I also set the second button’s state to be hidden.

So we still have the same screen, less one button.

Next we want to add an event to the button, like so:

var btnCardOne = new Ext.Button( В В В В html: 'Card 1 Button', В В В В handler: function ()  В В В В В В В В rootPanel.setActiveItem(1,  type: 'slide' ); В В В В В В В В btnCardOne.setVisible(false); В В В В В В В В btnCardTwo.setVisible(true); В В В В  );

var btnCardTwo = new Ext.Button( В В В В docked: 'right', В В В В hidden: true, В В В В html: 'Card 2 Button', В В В В handler: function ()  В В В В В В В В rootPanel.setActiveItem(0,  type: 'slide' ); В В В В В В В В btnCardOne.setVisible(true); В В В В В В В В btnCardTwo.setVisible(false); В В В В  );

 

Because the buttons are just local variables we can access them in each event, so in the first button, we want to set the active item (card) to 1, turn off button one, and turn on button two.

Then in the second button, we do the opposite. Now clicking each button flicks between the two.

  

Categories: Sencha Touch Tags: frameworks, mobile

Comments (3)

ben

August 4th, 2011 at 01:58 | #1

Reply |

Quote

Hello Phillip,

thanks very much for the article!

Why don”t you just use the tabpanel with the tabbar at the bottom. I think tabbar looks much nicer as it gives you the iphone gui look at the bottom with nice icons, although I am not sure how you can hide a button in the tab bar though.

In my case, I want to create a home panel but with no button in the tab bar. The home button will be on the top toolbar. Not sure if i can achieve that using tabpanel.

pls let me know if you any ideas

Phillip

August 4th, 2011 at 13:21 | #2

Reply |

Quote

Hey Ben,

I was actually trying to solve a specific scenario at the time that isn”t really supported by the framework. Something along the lines of:

Display a list of data, click a button to flick to a specific panel, add some options, go back to the list of data and have the new options applied. Between the different panels the buttons change.

I attempted to use the tab panel, but the way they are docked made it really difficult since the options that changed were on the bottom, but options that didn”t change were above. It was resulting in a lot of duplication, and was easier solved by just hiding/showing the button depending on the panel being shown.

The blog post however doesn”t have any of the complexity I was facing at the time. I haven””t touched Sencha since this post since it doesn”t support tables at the moment so we can”t use it for our project.

Phill

Romy

October 6th, 2011 at 12:15 | #3

Reply |

Quote

wow! thanks! you rule. this was so helpful. it helped me get over a bad point. nice stuff for beginners.

Comments are closed.

Getting Started – NServiceBus with Multiple Startup Projects

Joining the Windows Phone 7 Club

RSS

Google

Youdao

Xian Guo

Zhua Xia

My Yahoo!

newsgator

Bloglines

iNezha

Twitter

Me

Twitter: philliphaydon

StackOverflow: phill

GitHub: phillip-haydon

CodeSchool: philliphaydon

KickStarter: phillip-haydon

Blogroll

Gareth Goodman

Jospeh Flood

Mindscape

Nick Harris

Nick Randolph

Phil Jones

Sal Mograby

Recent Posts

Using Partial Renders with Nancy rather than Render Actions like MVC

My volume gets lowered/reduced when swapping applications (solution)

Nancy and Content Negotiation

Sinatra Book Review

Keep an eye on Raygun to zap all your errors away.

Running 2 queries is fine, you don&rsquo;t need to ALWAYS eager load!

Raven.DynamicSession for RavenDB

Nancy and Areas

RavenDB&hellip; What am I persisting, what am I querying? (part 3)

RavenDB&hellip; What am I persisting, what am I querying? (part 2)

Meta

Log in

Entries RSS

Comments RSS

WordPress.org

Categories

.NET 2.0

ClientID

EntityFramework

Facepalm

Fluent NHibernate

General

LightSpeed

Linq2Sql

MVC

MongoDB

Moq

NHibernate

NServiceBus

NancyFX

OrmLite

Profiling

QueryOver

Rant

RavenDB

Sencha Touch

Service Stack

Uncategorized

Unit Testing

WCF

Web Forms

Windows

Windows Phone 7

jQuery

Archive

December 2011 (4)

December 2010 (5)

November 2012 (4)

November 2011 (4)

November 2010 (1)

October 2012 (3)

October 2011 (3)

October 2010 (3)

September 2012 (1)

September 2011 (1)

September 2010 (2)

August 2011 (4)

July 2012 (3)

July 2011 (3)

July 2009 (1)

June 2012 (3)

June 2011 (2)

May 2011 (3)

April 2012 (1)

April 2011 (4)

March 2012 (4)

March 2011 (1)

February 2012 (2)

February 2011 (1)

January 2012 (1)

January 2011 (6)

Top

WordPress

Copyright &copy; 2009-2012 Phillip Haydon

Theme by NeoEase. Valid XHTML 1.1 and CSS 3.

# December 9, 2012 6:33 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)