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
Suppose the dynobj has a specific type. Such as
Now let us chane the type Table to generic object type as
Now we will come to dynamic binding. We gave following example in the previous section
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 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.
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.
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.
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.
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.
|All times are GMT +5.5. The time now is 05:09.|