Chapter 13 - Dynamic type and DLR

The content and code of this article is referenced from book Pro C#5.0 and the .NET 4.5 Framework by Apress. The intention of the writing is to review the konwledge and gain better understanding of the .net framework. 

 

1. The role of C# dynamic keyword

We learned implicit varaiable in early chapters, and once the initial assignment has been made, you have a strong typed variable, any attemp to assign an imcompatible value will result in a compiler error. 

    static void ImplicitVariable()
        {
            var a = new List<int> ();
            a.Add (90);

            a = "hello"; //compiler error
        }

With the release of .net 4.0, the C# language introduced a keyword named dynamic. From a high level, you can consider the dynamic keyword a specialized form of System.Object, any value can be assigned to a dynamic data type. 

What makes a dynamic variable much different from a variable declared implicitly or via a System.Object referent is that it is not strongly typed. Dynamic variable can be assigned with any initial value, and can be reassigned to any new value during its lifetime. 

        static void ChangeDynamicData()
        {
            dynamic t = "hello";

            t = false;

            t = new List<int> ();

        }

 

1.1 Calling member on dynamic data

To invoke methods on dynamic variable, just apply the dot operator and specify a public member. However, the validity of the members you specify will not be checked by the compiler. 

        static void InvokeMemberOnDynamicData()
        {
            dynamic data = "hello";
            Console.WriteLine (data.ToUpper ());

            Console.WriteLine (data.toupper ()); //compile file, will have runtime error
        }

1.2 The role of Microsoft.CSharp.dll 

When you create a new visual studio C# project, you will automatically have a reference set to an assembly Microsoft.CSharp.Dll. The most common class, RuntimeBinderException, represents an error that will be thrown if you attempt to invoke a member on a dynamic data, which does not exist. 

        static void InvokeMemberOnDynamicData()
        {
            dynamic data = "hello";
            try
            {
                Console.WriteLine (data.ToUpper ());
                Console.WriteLine (data.toupper ()); 
            }
            catch(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex) {
                Console.WriteLine (ex.Message);
            }
        }

 

1.3 The scope of dynamic keyword

The var keyword can never be used as a return value, a parameter, or a member of a class/structure. This is not the case with dynamic keyword. 

    class dynamicClass
    {
        private static dynamic dField;

        public dynamic Property {get;set;}

        public dynamic method(){
            return 1;
        }
    }

 

1.4 Limitations of the dynamic keyword

While a great many things can be defined using the dynamic keyword, there are some limitations reagarding its usage. The dynamic data item can not make use of lambda expression or C# anonymous methods when calling a methods.  In addition, it has very limited use within LINQ to objects and other LINQ technologies. 

 

1.5 Practise use of the dynamic keyword

In a few circumstances, the dynamic keyword can radically reduce the amount of code you need to write. Specifically, if you are building .net applications that make heavy use of late binding. As well, if you are building a .net application that needs to communicate with legacy COM library. 

The use of dynamic keyword is a trade-off between brevity of code, and type safety. 

 

2. The role of Dynamic Language Runtime (DLR)

With the release .net 4.0, the Common Language Runtime (CLR) was supplemented with a complementary runtime environment named the Dynamic Language Runtime (DLR). In a nutshell, a dynamic runtime allows a dynamic language the ability to discover types completely at runtime with no compile-time checks. 

2.1 The role of expression trees

The DLR makes use of expression trees to capture the meaning of a dynamic call in neutral terms. 

 

2.2 The role of System.Dynamic namespace

The system.Core.dll assembly includes a namespace named System.Dynamic. You will only make use of the namespace if you want to build a custom runtime builder. 

2.3 Dynamic Runtime lookup of expression trees

If the dynamic data type is pointing in memory to a COM object, the expression tree is sent to a low-level COM interface named IDispatch. 

If the dynamic data is not pointing to a COM object, the expression tree may be passed to an object implementing the IDynamicObject interface. This interface is used behind the scenes to allow language such as IronRuby, to take expression tree and map it to ruby specifies.

If the dynamic data is pointing to a normal C# object, the expression tree is dispatched to C# runtime binder. 

After the expression tree has been processed by a given binder, the dynamic data will be resolved to the real in-memory data type. 

 

2.4 Late bind calls using dynamic types

//normal procedures of late binding using reflection
        static void LateBinding(Assembly asm)
        {
            try{
                Type car = asm.GetType("CarLibrary.Car");

                object myCar = Activator.CreateInstance(car);

                MethodInfo method = car.GetMethod("Print");

                method.Invoke(myCar, null);
            }
            catch(Exception ex) {
                Console.WriteLine (ex.Message);
            }
        }
        //using dynamic
        static void LateBinding(Assembly asm)
        {
            try{
                Type car = asm.GetType("CarLibrary.Car");

                dynamic myCar = Activator.CreateInstance(car);
                myCar.Print();
            }
            catch(Exception ex) {
                Console.WriteLine (ex.Message);
            }
        }

By declaring the myCar using dynamic, the heavy lifting of reflection is done using DRL. 

 

posted @ 2015-04-14 13:33  tim_bo  阅读(181)  评论(0编辑  收藏  举报