got net?

Kevin Hazzard's Brain Spigot

About the author

Welcome to Kevin Hazzard's blog.
E-mail me Send mail

Recent comments

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2009

The Missing System.Dynamic.DynamicObject Class

If you've got a copy of the Visual Studio 2010 CTP and you've been watching the presentations done by Anders Hejlsberg and Jim Hugunin at the Microsoft Professional Developer's Conference 2008, you may be wondering where the DynamicObject class is. It's not in the CTP. If you snoop around in the System.Scripting.Actions namespace, you'll find some of the required pieces but the actual DynamicObject class used in the demos just isn't there.

There's nothing magical about the DynamicObject class. It's a pretty simple IDynamicObject implementation that maps calls through the MetaObject for the DynamicObject as follows:

  • MetaObject.GetMember => DynamicObject.GetMember
  • MetaObject.SetMember => DynamicObject.SetMember
  • MetaObject.Invoke => DynamicObject.Invoke
  • MetaObject.Call => DynamicObject.InvokeMember

Of couse, these little "dispatchers" just set up the expression tree tests and targets as Jim described in his talk. Curt Hagenlocher was kind enough to provide a copy of the DynamicObject source code which can be found here. Thanks, Curt! I've also included the source code here, too. If you include this class in your project, the VS2010 CTP demos that Anders and Jim showed at PDC2008 will work just fine.

/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 *
 * ***************************************************************************/

using System;
using System.Collections.Generic;

using System.Linq.Expressions;
using System.Scripting.Actions;

namespace System.Dynamic {
    public class DynamicObject : IDynamicObject {
        public virtual object GetMember(GetMemberAction info) {
            throw new MissingMemberException("Dynamic", info.Name);
        }
        public virtual void SetMember(SetMemberAction info, object value) {
            throw new MissingMemberException("Dynamic", info.Name);
        }

        public virtual object Invoke(InvokeAction info, object[] arguments) {
            throw new NotImplementedException("Invoke");
        }

        public virtual object InvokeMember(CallAction info, object[] arguments) {
            throw new NotImplementedException("InvokeMember");
        }

        public MetaObject GetMetaObject(Expression parameter) {
            return new DynamicMetaObject(this, parameter);
        }

        class DynamicMetaObject : MetaObject {
            public DynamicMetaObject(DynamicObject v, Expression e) : base(e, Restrictions.Empty, v) { }

            public override MetaObject GetMember(GetMemberAction info, MetaObject[] args) {
                var x = this.Expression;
                var test = Expression.TypeIs(x, typeof(DynamicObject));
                var target = Expression.Call(
                                  Expression.Convert(x, typeof(DynamicObject)),
                                  typeof(DynamicObject).GetMethod("GetMember"),
                                  Expression.Constant(info));
                return new MetaObject(target, Restrictions.ExpressionRestriction(test));
            }

            public override MetaObject SetMember(SetMemberAction info, MetaObject[] args) {
                var x = this.Expression;
                var y = args[1].Expression;
                var test = Expression.TypeIs(x, typeof(DynamicObject));
                var target = Expression.Call(
                    Expression.Convert(x, typeof(DynamicObject)),
                    typeof(DynamicObject).GetMethod("SetMember"),
                    Expression.Constant(info),
                    Expression.ConvertHelper(y, typeof(object)));
                return new MetaObject(target, Restrictions.ExpressionRestriction(test));
            }

            public override MetaObject Invoke(InvokeAction action, MetaObject[] args) {
                var x = this.Expression;
                var test = Expression.TypeIs(x, typeof(DynamicObject));
                var inits = new Expression[args.Length - 1];
                for (int i = 0; i < inits.Length; i++) {
                    inits[i] = Expression.ConvertHelper(args[i + 1].Expression, typeof(object));
                }
                var argsArray = Expression.NewArrayHelper(typeof(object), inits);
                var target = Expression.Call(
                    Expression.Convert(x, typeof(DynamicObject)),
                    typeof(DynamicObject).GetMethod("Invoke"),
                    Expression.Constant(action), argsArray);
                return new MetaObject(target, Restrictions.ExpressionRestriction(test));
            }

            public override MetaObject Call(CallAction action, MetaObject[] args) {
                var x = this.Expression;
                var test = Expression.TypeIs(x, typeof(DynamicObject));
                var inits = new Expression[args.Length - 1];
                for (int i = 0; i < inits.Length; i++) {
                    inits[i] = Expression.ConvertHelper(args[i + 1].Expression, typeof(object));
                }
                var argsArray = Expression.NewArrayHelper(typeof(object), inits);
                var target = Expression.Call(
                    Expression.Convert(x, typeof(DynamicObject)),
                    typeof(DynamicObject).GetMethod("InvokeMember"),
                    Expression.Constant(action), argsArray);
                return new MetaObject(target, Restrictions.ExpressionRestriction(test));
            }
        }
    }
}

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by kevin on Tuesday, November 11, 2008 7:04 PM
Permalink | Comments (1) | Post RSSRSS comment feed

Related posts

Comments

blogs.microsoft.co.il

Monday, November 24, 2008 4:23 PM

pingback

Pingback from blogs.microsoft.co.il

Using PDC bits with new “Dynamic” features - Ariel's Remote Data Center

Add comment


(Will show your Gravatar icon)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Live preview

Wednesday, January 07, 2009 5:55 AM