300
❘
CHAPTER 14
InteractIng wIth the DLr
CONSIDERINg DyNAMICSITE
When working with a static language such as C# or Visual Basic.NET, the compiler knows what to
emit in the form of MSIL based on the code the developer provides. However, dynamic code isn’t
static — it can change based on any of a number of factors. One problem with dynamic languages
is that DLR doesn’t always know what to emit during compile time because the real time event
hasn’t occurred yet. Of course, the static language still needs some code in place because static lan-
guages need to know what to do at compile time. This seeming conundrum is handled by invoking a
DynamicSite
object. Using a
DynamicSite
object means that the static language knows what to call
at compile time and DLR can fill the
DynamicSite
object with executable code during run time.
As with many parts of DLR, the action takes place behind the scenes — you don’t even know it
occurs. However, it’s useful to know what happens so you at least know what to suspect when an
error occurs. The act of invoking the
DynamicSite
method creates an operation to perform and a
delegate. The delegate contains caching logic that is updated every time the arguments change. In
short, as the dynamic language changes, DLR generates events that change the content of the cache
as well.
At the center of working with
DynamicSite
is the
UpdateBindingAndInvoke()
method. The first
time that application code calls the
DynamicSite
object, the
UpdateBindingAndInvoke()
method
queries the arguments for the specified code. For example, the code might be something simple such
as
x + y
, so the query would request the types of
x
and
y
. At this point,
UpdateBindingAndInvoke()
generates a delegate that contains the implementation of the code.
The next time the application invokes the
DynamicSite
object, the delegate checks the arguments
in the call against those in the cache. If the argument types match, then the delegate simply uses the
current implementation of the code. However, if the arguments are different, then the delegate calls
UpdateBindingAndInvoke()
, which creates a new delegate that contains a definition of the new code
with the updated arguments. The new delegate contains checks for both sets of argument types and
calls the appropriate implementation based on the arguments it receives. Of course, if none of the argu-
ment sets match the call, then the process starts over again with a call to
UpdateBindingAndInvoke()
.
Do'stlaringiz bilan baham: |