Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C# (http://www.go4expert.com/articles/c-sharp-tutorials/)
-   -   Understanding Dynamic Binding in C# (http://www.go4expert.com/articles/understanding-dynamic-binding-c-sharp-t30004/)

shabbir 16Feb2014 19:22

Understanding Dynamic Binding in C#
 
C# is a strongly typed language: You might have heard this sentence numerous times. Have you ever wondered, what does that actually mean? We are here with the answer to this question and we would introduce to another fairly advanced and extremely interesting .NET concept, known as dynamic binding. But before that, let us shed some light on strongly typed languages.

A strongly typed language is a language where types, members and variables, all are resolved at compile time by the compiler. For example, when you store an object of some type into variable of some other type, the compiler prompts you that you cannot do such type of assignment where types doesn’t match and code isn’t compiled. It means that type resolution is done before program is executed. It saves your code from many errors that can arise on run time and can cause your program to crash. C# is also a strongly typed language; as a matter of fact, all of the .NET languages are strongly typed. Though, strongly typed languages have uncountable advantage; however, in some cases we might want that types and member variables of our code be resolved at run time, instead of compile time. This where concept of dynamic binding comes into play, which is the topic of discussion for this article.

Simply put; dynamic binding refers to delaying the process of type resolution from compile time to runtime. We need dynamic binding when we know that a certain type or member variable exists but compiler has no idea about that type or member function. In such cases we tell the compiler that since you do not know anything about this type yet, therefore you shouldn’t bother about resolving it at the moment; we will resolve it at the run time. You might want to dynamically resolve types in scenarios where you are interoperating with dynamic platforms such as COM and IronPython or when you are using reflections in your code.
In order to utilize dynamic binding in C# on any particular object, the keyword dynamic is used. For example
Code:

dynamic dynobj = GetAnyObject();
dynobj.AddData();

Actually the above lines of code are telling the compiler that we have a type dynobj which is dynamic and then we call the method AddData on that dynamic type. Actually what happens is that compiler will try to bind the dynobj object to AddData, but since we have declared dynobj, dynamic, it will tell the compiler that please done bind AddData with dynobj at the moment, we want to bind it on run time. To further understand the concept, first understand how compiler statically binds the type and members.

Static Vs Dynamic Bind



Suppose the dynobj has a specific type. Such as
Code:

Table dynobj = new Table();
dynobj.AddData();

In this case the compiler will search the AddData method in following order and will bind it statically to the dynobj object type.
  • First, the compiler will try to find a method named AddData which takes no parameter in the type Table.
  • Then it will find AddData method in the methods that take optional parameter.
  • If it still can’t find the AddData method, it will find the method in the base class of type table.
  • If still not found, it will try to search for extension methods that take Table type as their first parameter.
If all of the above conditions are false, the compiler will generate an error that it cannot find the AddData method therefore the code cannot be compiled. This is actually static binding.
Now let us chane the type Table to generic object type as
Code:

object dynobj = new Table();
dynobj.AddData();

In this case, the value stored in the dynobj might contain method AddData, but compiler doesn’t know that. Compiler only has the information about the variable type i.e object in this case; therefore, it will try to find the AddData method in the object variable and will off course not find it and will give compile time error.

Now we will come to dynamic binding. We gave following example in the previous section
Code:

dynamic dynobj = GetAnyObject();
dynobj.AddData();

Actually dynamic objects are also non-descriptive similar to the object data type which we aforementioned. The difference between a static non-descriptive object and a dynamic non-descriptive object is that it lets you compile the code without resolving the types on compile type. A dynamic objet resolves the type on runtime based on its runtime type instead of compile time type.

When the compiler sees the dynamic expression (Expression with keyword dynamic), it will not resolve the types and members and will not bind anything but simply package the expression and will wait for runtime binding.

Dynamic bind has two types. If the dynamic object implements the IDynamicMetaObjectProvider, binding will be done by that interface. In the other case, dynamic bind would be done as if it would have been done, had the compiler known the runtime type of the dynamic object. These two types of binding are also referred as custom binding and the language binding. We would see both of them in detail.

Custom Binding



Custom binding is the type of binding that occurs when an object implements IDynamicMetaObjectProvider. You can create an object in C# and implement this IDOMP interface to utilize the dynamic binding capabilities. However, more commonly, IDOMP objects are acquired from languages that are dynamically implemented in .NET such as IronRuby and IronPython. These languages use dynamic language runtime or DLR for dynamic binding purposes. The objects in these classes implicitly implement the IDOMP interface; therefore dynamic binding occurs by default while resolving the types, members and methods of those types. In order to further elaborate the concept of custom binding, have a look at our first example.

Example1

Code:

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

namespace CSharpTutorial
{
    public class Table : DynamicObject
    {
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
                Console.WriteLine(binder.Name + "method was dynamically called");
                result = null;
                return true;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            dynamic dynobj = new Table();
            dynobj.AddData();
            dynobj.GetData();
            Console.ReadLine();
        }
    }
}

Carefully look at the code in Example1, we first import the namespace Dynamic. This name space contains DynamicObject class which inherits IDynamicMetaObjectProvider. We created a class named Table and inherited it from DynamicObject class which inherits IDMOP. That means now our Table class also implements the IDOMP interface which means that dynamic binding on the object of Table class will be custom binding.

Inside our Table class we have override TryInvokeMember method of the DynamicObject class which we have inherited. Now whenever, compiler dynamically tries to bind the object which implements IDMOP, this method will also be called. The parameter binder of this method actually contains the information regarding the method which is being dynamically bound.

Now come to the main method, here we have declared dynamic object dynobj of type Table. We have then called AddData and then GetData methods on the dynobj object. Table class doesn’t contain these two methods but you will see that the compiler will still compile the code without any error and will defer the binding till the run time. This is due to the fact that we have made the dynobj object dynamic. If the dynobj object was not dynamic, the compiler would have generated an error on compile time and our code would not have compiled. Now, when you call AddData and GetData method on the dynobj object, the TryInvokeMember method of the Table class will be invoked twice and inside the method we have printed the invoker’s name. The output of Example1 will be as follows.

Output1

http://imgs.g4estatic.com/c-sharp/dy...ng/output1.png

Language Binding



Language binding is another type of dynamic binding. In language binding, the object doesn’t implement IDMOP interface. Usually language binding is used in order to avoid inherent problems in implicit .NET binding and scenarios where types are imperfectly designed. A typical example of using language binding is with numeric types because numeric types do not contain any common interface. In such scenarios we can declare a dynamic method with dynamic parameter and operator type to perform arithmetic on runtime. In our Example2, we will show you that how you can do that.

Example2

Code:

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

namespace CSharpTutorial
{
    class Program
    {
        static dynamic Average(dynamic num1, dynamic num2)
        {
            return ((num1 + num2) / 2);
        }

        static void Main(string[] args)
        {
            int num1 = 8;
            int num2 = 4;
            Console.WriteLine(Average(num1,num2));   
            Console.ReadLine();
        }
    }
}

In this case all the type resolution and method bindings will be delayed till runtime. This technique is helpful but it comes with potential drawbacks as well. The security you gain from static type checking is not available in this case. Another drawback of dynamic binding is that it comes with performance hit because of the dynamic language runtime’s caching mechanism. However, repeated calls to same function can be optimized and performance hits can be mitigated to some extent.

Dynamic Binding Exception Handling



We saw in our previous section that we use dynamic binding when we want to bind members that we know but compiler doesn’t know, therefore no compile time exception occurs. However, scenario may arise where members we are trying to bind are not available at runtime as well. In such cases an exception is thrown, known as RuntimeBinderException. Consider a simple example of an integer type which is defined dynamically. If we call some method which is not available on integer type, on a dynamically created object which is referring to an integer type, RuntimeBinderException will be thrown. This concept is best explained with the help of an example. Have a look at Example3 to further grasp this concept.

Example3

Code:

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

namespace CSharpTutorial
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic dynobj = 10;
            dynobj.AddData();   
            Console.ReadLine();
        }
    }
}

In Example3, we have created a dynamic object dynobj and have stored an integer variable in this dynamic object. When we call AddData method on this object, the compiler will not generate an error because it has deferred the binding till runtime. At runtime, the compiler will try to link AddObject method with the dynobj object but since dynob is referring to an integer value which is 10, and integer doesn’t contain any method AddData which could be linked to it on runtime, therefore a RuntimeBinderExceptiop will be thrown. Now if you try to run the code in VS 2010 in debug mode it will have the following output.

Output3

http://imgs.g4estatic.com/c-sharp/dy...ng/output3.png

You can implement exception handling mechanism to handle such exceptions.

Dynamic type and object type is almost identical with only exception that dynamic type allows you to resolve types and members dynamically. If you call typeof on a dynamic and object type the result would be same. This concept also extends to dynamic arrays and constructed types. Another similarity between a dynamic and object type is that a dynamic type can point to object of any type like an object reference with the exception of pointer type.

Dynamic types and object types can be interconverted. This will be best explained with the help of small example. Have a look at Example4.

Example4
Code:

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

namespace CSharpTutorial
{
    class Program
    {
        static void Main(string[] args)
        {
            object obj = new System.Text.StringBuilder();
            dynamic dynobj = obj;
            dynobj.Append("go4Expert");
            Console.WriteLine(obj);
            Console.ReadLine();
        }
    }
}

In Example4, we have simply declared an obj which can store a string builder object. Next we have declared another object dynobj of type dynamic and stored the reference of obj in it. We then called Append method of the StringBuilder class to append data to the string. Because now dynamic dynobj object is referring object type obj; therefore changes made by dynamic object will be reflected in actual object obj as well. We then printed the value of obj which now has a string. The output of Example4 is as follows.

Output4

http://imgs.g4estatic.com/c-sharp/dy...ng/output4.png


All times are GMT +5.5. The time now is 16:50.