Dynamic Objects

We can create our own dynamic type by extending the DynamicObject type.


using System;
using System.Dynamic;

using System.Reflection;
using System.Collections.Generic;


public class MyDynamic: DynamicObject
{
    public override bool TryInvokeMember(
    InvokeMemberBinder binder, object[] args, out object result)
    {
        Console.WriteLine(binder.Name + " method was called");
        result = null;
        return true;
    }
}
public class Test
{
    static void Main()
    {
        dynamic d = new MyDynamic();
        d.MethodA();  
        d.MethodB(); 
    }
}

The output:


MethodA method was called
MethodB method was called

DynamicObject exposes other virtual methods that enable consumers to use other programming constructs as well.

The following correspond to constructs that have representations in C#:

MethodProgramming construct
TryInvokeMemberMethod
TryGetMember, TrySetMemberProperty or field
TryGetIndex, TrySetIndexIndexer
TryUnaryOperationUnary operator such as !
TryBinaryOperationBinary operator such as ==
TryConvertConversion (cast) to another type
TryInvokeInvocation on the object itself e.g., d("foo")

The following demonstrates TryBinaryOperation and TryInvoke:


using System;
using System.Dynamic;
using System.Xml.Linq;
using System.Reflection;
using System.Collections.Generic;


public class Duck : DynamicObject
{
    public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result)
    {
        Console.WriteLine(binder.Operation); 
        result = "foo";
        return true;
    }

    public override bool TryInvoke(InvokeBinder binder,
    object[] args, out object result)
    {
        Console.WriteLine(args[0]); 
        result = 123;
        return true;
    }
}


public class Test
{
    static void Main()
    {
        dynamic d = new Duck();
        Console.WriteLine(d + d); 
        Console.WriteLine(d(78, 'x')); 
    }
}

The output:


Add
foo
78
123

The following example extends the DynamicObject class to create a wrapper around a dictionary.

Calls to get and set properties on the dynamic type are mapped to the key/value pairs contained in the dictionary:

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Dynamic;

class MainClass
{
    static void Main(string[] args)
    {

        dynamic dynamicDict = new MyDynamicDictionary();
        // Set some properties. 
        Console.WriteLine("Setting property values");
        dynamicDict.FirstName = "Adam";
        dynamicDict.LastName = "Freeman";

        // Get some properties. 
        Console.WriteLine("\nGetting property values");
        Console.WriteLine("Firstname {0}", dynamicDict.FirstName);
        Console.WriteLine("Lastname {0}", dynamicDict.LastName);

        // Call an implemented member. 
        Console.WriteLine("\nGetting a static property");
        Console.WriteLine("Count {0}", dynamicDict.Count);

        Console.WriteLine("\nGetting a non-existent property");
        try
        {
            Console.WriteLine("City {0}", dynamicDict.City);
        }
        catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException e)
        {
            Console.WriteLine("Caught exception");
        }
    }
}
class MyDynamicDictionary : DynamicObject
{
    private IDictionary<string, object> dict = new Dictionary<string, object>();

    public int Count
    {
        get
        {
            Console.WriteLine("Get request for Count property");
            return dict.Count;
        }
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        Console.WriteLine("Get request for {0}", binder.Name);
        return dict.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        Console.WriteLine("Set request for {0}, value {1}", binder.Name, value);
        dict[binder.Name] = value;
        return true;
    }

}

The output:


Setting property values
Set request for FirstName, value Adam
Set request for LastName, value Freeman

Getting property values
Get request for FirstName
Firstname Adam
Get request for LastName
Lastname Freeman

Getting a static property
Get request for Count property
Count 2

Getting a non-existent property
Get request for City
Caught exception
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.