Commit 9057654
committed
[Java.Interop.Dynamic] Support accessing static
(I now understand the DLR enough to be slightly dangerous.)
Implement enough DLR voodoo so that static int fields can be accessed
and read; from a unit test:
dynamic Integer = new DynamicJavaClass ("java/lang/Integer");
int max = Integer.MAX_VALUE;
Yes, that works, and yes, it is awesome. It reads the
Integer.MAX_VALUE field.
Doubly awesome -- and a huge part of the complication! -- is that it
uses DynamicMetaObject.BindConvert() to detect that the field type
is `int`, as field type information is required in order to lookup the
field, and thus we need to delay the actual JNI field lookup and
access until *after* we know the desired type. Figuring out how to
actually support this took a fair bit of banging my head against
several walls...
...and since the DLR documentation is horribly inadequate, requiring
that I go spelunking through their source...
A Short DLR Primer:
The DLR is ~wholly based upon Systme.Linq.Expressions. A type may
participate in the DLR by implementing the IDynamicMetaObjectProvider
interface and subclassing the DynamicMetaObject class.
DynamicMetaObject does the "heavy lifting" of Expression manipulation
in order to perform the desired actions.
The problem, sanity wise, is understanding BindingRestrictions use,
which is likewise underdocumented:
return new DynamicMetaObject(
Expression,
BindingRestrictions.GetTypeRestriction(
Expression,
typeof (DynamicJavaClass)));
AFAICT, BindingRestrictions is used by the DLR to assist in
"invalidating" the cached callsite information (as LOTS of information
is cached at the callsite in order to assist performance).
The above states that `Expression` will be of type `DynamicJavaClass`,
via BindingRestrictions.Get*Type*Restriction(), and thus:
1. If the cached type is NOT DynamicJavaClass, then it's the cached
value, and nothing more need be done.
2. If the cached type IS DynamicJavaClass, then
DynamicJavaClass.GetMetaObject() should be invoked for future DLR
operations.
The problem regarding the above "don't do anything until we get a
BindConvert() request!" logic is that BindConvert() is *last*.
Furthermore, DynamicMetaObject instances are recreated ALL THE TIME,
so accessing a static field:
var value = Integer.MAX_VALUE;
Results in (paraphrasing greatly!):
var metaObject = Integer.GetMetaObject();
var valueObject = metaObject.BindGetMember(... "MAX_VALUE" ... );
var value = valueObject.Compile().Invoke (...);
At this point `value` is compared against the BindingRestrictions; if
BindingRestrictions is set improperly, then `value` is used AS-IS,
there is no later BindConvert() call, and there's no way to determine
the intended field type. (Exceptions soon follow.)
So to make this work the MetaStaticMemberAccessObject.BindGetMember()
method needs to restrict the value to a StaticFieldAccess, which is
created via System.Linq.Expressions, so that the StaticFieldAccess can
participate in the DLR binding logic.
StaticFieldAccess holds the accessed field and, in turn, implements
the IDynamicMetaObjectProvider to return a MetaStaticFieldAccessObject,
which overrides BindConvert() and delegates the call to
DynamicJavaClass.GetStaticFieldValue(), which allows providing both
the accessed field AND the desired return type, allowing this miracle
to actually work.
Huzzah!int fields.1 parent 1c90502 commit 9057654
File tree
3 files changed
+141
-7
lines changed- src/Java.Interop.Dynamic
- Java.Interop.Dynamic
- Tests/Java.Interop.Dynamic
3 files changed
+141
-7
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
40 | 50 | | |
Lines changed: 115 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
| 8 | + | |
7 | 9 | | |
8 | 10 | | |
| 11 | + | |
| 12 | + | |
9 | 13 | | |
10 | 14 | | |
11 | 15 | | |
12 | 16 | | |
13 | 17 | | |
14 | 18 | | |
15 | | - | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
16 | 55 | | |
17 | | - | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
18 | 68 | | |
19 | 69 | | |
20 | 70 | | |
21 | | - | |
| 71 | + | |
22 | 72 | | |
23 | | - | |
| 73 | + | |
24 | 74 | | |
25 | 75 | | |
| 76 | + | |
| 77 | + | |
26 | 78 | | |
27 | 79 | | |
28 | 80 | | |
29 | 81 | | |
| 82 | + | |
30 | 83 | | |
31 | 84 | | |
32 | 85 | | |
33 | 86 | | |
34 | 87 | | |
35 | | - | |
| 88 | + | |
| 89 | + | |
36 | 90 | | |
37 | 91 | | |
38 | 92 | | |
| |||
42 | 96 | | |
43 | 97 | | |
44 | 98 | | |
45 | | - | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
46 | 110 | | |
47 | 111 | | |
48 | 112 | | |
| |||
55 | 119 | | |
56 | 120 | | |
57 | 121 | | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
58 | 167 | | |
59 | 168 | | |
60 | 169 | | |
| |||
Lines changed: 16 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
19 | 25 | | |
20 | 26 | | |
21 | 27 | | |
22 | | - | |
| 28 | + | |
| 29 | + | |
23 | 30 | | |
24 | 31 | | |
25 | 32 | | |
| |||
35 | 42 | | |
36 | 43 | | |
37 | 44 | | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
38 | 53 | | |
39 | 54 | | |
40 | 55 | | |
0 commit comments