Things to remember when creating delegates and doing LCG...
In my AcquiringObjectDataSource
articles part three I promised to show what things look like using the DynamicCall
library I've previously posted. In doing that, I've had to make the DynamicCall
stuff work with static
methods. Previously I had inserted some code to start handling statics
deep inside the Build
methods, but I've certainly never gotten to the point of using them. Sorry to anyone that tried, I should have documented that code as not-yet working.
Anyway, last night I worked into the wee hours of the morning getting everything hooked up for static
methods. In the process I learned some things that I thought I would dump now. In an upcoming post, I'll talk about the changes to the DynamicCall
library, but for now:
- When you create a delegate for a
static
method, the delegate signature should not include a "this" reference. Duh. This manifests itself in the error message below when callingCreateDelegate
. This happens because the delegate definition expects a "this" pointer as the first method argument, but the generatedDynamicMethod
doesn't have one. This spawned a whole new set ofStaticProc
andStaticFunc
delegate definitions.ArgumentException: Error binding to target method
- If you get the delegate definition correct, but don't generate the right code, it'll hurl at JIT with the message below. Note that the generation of the LCG
DynamicMethod
is fine, the delegate binding is fine. The JIT of the first caller to that delegate is where things will pop. This is often very in the runtime, which is bad.System.InvalidProgramException: Common Language Runtime detected an invalid program.
- Not strictly related to
static
method supprt, but I rediscovered that you can't access private members of a class unless theDynamicMethod
was properly bound to that class. This resulted in me still having to know the class of thestatic
method, even though there's no "this" pointer to deal with. - Ruthless refactoring makes things much easier. Doing this work on the
DynamicCall
library has really cleaned things up, I'll give more detail in a later post.
As it stands now binding to a static
method now looks like this:
StaticProc<ObjectDataSourceView, ParameterCollection, IDictionary, IDictionary> s_MergeDictionaries =DynamicProcedure<ObjectDataSourceView, ParameterCollection, IDictionary, IDictionary>.Static.Initialize("MergeDictionaries", CreateParameterList.Auto);Dynamic<ObjectDataSourceView>.Static.Procedure.Explicit<ParameterCollection, IDictionary, IDictionary>.CreateDelegate("MergeDictionaries", CreateParameterList.Auto);
While this is really clear (I think), it is very verbose. The new C# 3.0 "var" feature will will make this much more readable:
var s_MergeDictionaries =DynamicProcedure<ObjectDataSourceView, ParameterCollection, IDictionary, IDictionary>.Static.Initialize("MergeDictionaries", CreateParameterList.Auto);Dynamic<ObjectDataSourceView>.Static.Procedure.Explicit<ParameterCollection, IDictionary, IDictionary>.CreateDelegate("MergeDictionaries", CreateParameterList.Auto);
UPDATE (27-July-2007 15:32): New syntax based on the latest round of refactorings on the DynamicCallDynamic<> class.
No comments:
Post a Comment