You remember the
previous post on dynamic. We will today look into it in a bit more detail. Yeah, let's ILDASM it and try and identify what is going on under the hood. But for the context of the post let's look at a simpler tale.
namespace Coderslog.Net4.Samples
{
public class SimpleDynamic
{
public void CallDoSomething()
{
var instance = GetDoSomething();
instance.DoSometing();
}
private dynamic GetDoSomething()
{
return new BehaviourA();
}
}
}
A very basic class, hmmm which roughly translates to something like, I might not be absolutely correct, but to get a fair idea, it is something like the following
public class SimpleDynamic
{
// Method: A Bit more involved than the reflection way, with Optimization
public void CallDoSomething()
{
object instance = this.GetDoSomething();
if (CallDoSometning_SiteContainer.delegatePlaceHolder == null)
{
CallDoSometning_SiteContainer.delegatePlaceHolder =
CallSite<Action<CallSite, object>>.Create(
new CSharpInvokeMemberBinder(
CSharpCallFlags.None,
"DoSometing",
typeof(SimpleDynamic),
null,
new []
{
new CSharpArgumentInfo(
CSharpArgumentInfoFlags.None
, null
)
}
));
}
CallDoSometning_SiteContainer.
delegatePlaceHolder.
Target.Invoke(
CallDoSometning_SiteContainer.delegatePlaceHolder
, instance);
}
//But theres an attribute on the object of
//Type:System.Runtime.CompilerServices.DynamicAttribute
private object GetDoSomething()
{
return new BehaviourA();
}
// Nested Types
//Compiler Generated Class- Internal Class
private static class CallDoSometning_SiteContainer
{
// Fields
public static CallSite<Action<CallSite, object>> delegatePlaceHolder;
}
}
So as you can see, the internal static class is there so as to ensure that, we don't always spend resources on the delegate, once it is evaluated.
If we look at the GetDomethingMethod, the Dydnamic Attribute on the returned object from the method GetDoSomething tells the run time that "
Indicates that the use of Object on a member is meant to be treated as a dynamically dispatched type.". If you notice the type of the static field is of type
CallSite<Action<CallSite, object>> is System.Runtime.CompilerServices..::.CallSite<(Of <(T>)>) {
MSDN: A dynamic call site base class. This type is used as a parameter type to the dynamic site targets.}.
Lets look at the place where all the action is happening, i.e. the method CallDoSomething. the method checks if the class CallDoSometning_SiteContainer.delegatePlaceHolder is populated or not, but if not it initializes it with the Create Method and you can notice ... CSharpInvokeMemberBinder {CompleteNamespace: Microsoft.CSharp.RuntimeBinder.CSharpInvokeMemberBinder} {MSDN: Represents a dynamic method call in C#, providing the binding semantics and the details about the operation. Instances of this class are generated by the C# compiler }.
This feels like .Net Reflection and one tends to ask, how optimized is it. Well, something Microsoft can enlighten us more about.