IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
PropertyAccessor.cs
Go to the documentation of this file.
1using System;
2using System.Reflection;
3using System.Reflection.Emit;
4
6{
7
8#if FIRST_PASS == false && EXPORTER == false && IMPORTER == false
9
13 internal abstract class PropertyAccessor
14 {
15
16 readonly Type type;
17 readonly string name;
18 PropertyInfo property;
19
26 protected PropertyAccessor(Type type, string name)
27 {
28 this.type = type ?? throw new ArgumentNullException(nameof(type));
29 this.name = name ?? throw new ArgumentNullException(nameof(name));
30 }
31
35 protected Type Type => type;
36
40 protected string Name => name;
41
45 protected PropertyInfo Property => AccessorUtil.LazyGet(ref property, () => type.GetProperty(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) ?? throw new InvalidOperationException();
46
47 }
48
53 internal sealed class PropertyAccessor<TProperty> : PropertyAccessor
54 {
55
64 public static PropertyAccessor<TProperty> LazyGet(ref PropertyAccessor<TProperty> location, Type type, string name)
65 {
66 return AccessorUtil.LazyGet(ref location, () => new PropertyAccessor<TProperty>(type, name));
67 }
68
69 Func<TProperty> getter;
70 Action<TProperty> setter;
71
77 public PropertyAccessor(Type type, string name) :
78 base(type, name)
79 {
80
81 }
82
86 Func<TProperty> Getter => AccessorUtil.LazyGet(ref getter, MakeGetter);
87
91 Action<TProperty> Setter => AccessorUtil.LazyGet(ref setter, MakeSetter);
92
98 Func<TProperty> MakeGetter()
99 {
100#if FIRST_PASS
101 throw new NotImplementedException();
102#else
103 var dm = DynamicMethodUtil.Create($"__<PropertyAccessorGet>__{Type.Name.Replace(".", "_")}__{Property.Name}", Type, false, typeof(TProperty), Array.Empty<Type>());
104 var il = JVM.Context.CodeEmitterFactory.Create(dm);
105
106 il.Emit(Property.GetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, Property.GetMethod);
107 il.Emit(OpCodes.Ret);
108 il.DoEmit();
109
110 return (Func<TProperty>)dm.CreateDelegate(typeof(Func<TProperty>));
111#endif
112 }
113
119 Action<TProperty> MakeSetter()
120 {
121#if FIRST_PASS
122 throw new NotImplementedException();
123#else
124 var dm = DynamicMethodUtil.Create($"__<PropertyAccessorSet>__{Type.Name.Replace(".", "_")}__{Property.Name}", Type, false, typeof(void), new[] { typeof(TProperty) });
125 var il = JVM.Context.CodeEmitterFactory.Create(dm);
126
127 il.Emit(OpCodes.Ldarg_0);
128 il.Emit(Property.SetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, Property.SetMethod);
129 il.Emit(OpCodes.Ret);
130 il.DoEmit();
131
132 return (Action<TProperty>)dm.CreateDelegate(typeof(Action<TProperty>));
133#endif
134 }
135
140 public TProperty GetValue() => Getter();
141
146 public void SetValue(TProperty value) => Setter(value);
147
148 }
149
155 internal sealed class PropertyAccessor<TObject, TProperty> : PropertyAccessor
156 {
157
165 public static PropertyAccessor<TObject, TProperty> LazyGet(ref PropertyAccessor<TObject, TProperty> location, Type type, string name)
166 {
167 return AccessorUtil.LazyGet(ref location, () => new PropertyAccessor<TObject, TProperty>(type, name));
168 }
169
170 Func<TObject, TProperty> getter;
171 Action<TObject, TProperty> setter;
172
178 public PropertyAccessor(Type type, string name) :
179 base(type, name)
180 {
181
182 }
183
187 Func<TObject, TProperty> Getter => AccessorUtil.LazyGet(ref getter, MakeGetter);
188
192 Action<TObject, TProperty> Setter => AccessorUtil.LazyGet(ref setter, MakeSetter);
193
198 Func<TObject, TProperty> MakeGetter()
199 {
200#if FIRST_PASS || IMPORTER || EXPORTER
201 throw new NotImplementedException();
202#else
203 if (Property.CanRead == false)
204 throw new InternalException($"Property {Property.Name} cannot be read.");
205
206 var dm = DynamicMethodUtil.Create($"__<PropertyAccessorGet>__{Property.DeclaringType.Name.Replace(".", "_")}__{Property.Name}", Type, false, typeof(TProperty), new[] { typeof(TObject) });
207 var il = JVM.Context.CodeEmitterFactory.Create(dm);
208
209 il.Emit(OpCodes.Ldarg_0);
210 il.Emit(OpCodes.Castclass, Type);
211 il.Emit(Property.GetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, Property.GetMethod);
212 il.Emit(OpCodes.Ret);
213 il.DoEmit();
214
215 return (Func<TObject, TProperty>)dm.CreateDelegate(typeof(Func<TObject, TProperty>));
216#endif
217 }
218
223 Action<TObject, TProperty> MakeSetter()
224 {
225#if FIRST_PASS || IMPORTER || EXPORTER
226 throw new NotImplementedException();
227#else
228 if (Property.CanWrite == false)
229 throw new InternalException($"Property {Property.Name} cannot be written.");
230
231 var dm = DynamicMethodUtil.Create($"__<PropertyAccessorSet>__{Property.DeclaringType.Name.Replace(".", "_")}__{Property.Name}", Type, false, typeof(void), new[] { typeof(TObject), typeof(TProperty) });
232 var il = JVM.Context.CodeEmitterFactory.Create(dm);
233
234 il.Emit(OpCodes.Ldarg_0);
235 il.Emit(OpCodes.Castclass, Type);
236 il.Emit(OpCodes.Ldarg_1);
237 il.Emit(Property.SetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, Property.SetMethod);
238 il.Emit(OpCodes.Ret);
239 il.DoEmit();
240
241 return (Action<TObject, TProperty>)dm.CreateDelegate(typeof(Action<TObject, TProperty>));
242#endif
243 }
244
250 public TProperty GetValue(TObject self) => Getter(self);
251
257 public void SetValue(TObject self, TProperty value) => Setter(self, value);
258
259 }
260
261#endif
262
263}
IKVM.Reflection.Type Type
IKVM.Reflection.PropertyInfo PropertyInfo
global::java.lang.invoke.LambdaForm.Name Name
@ PropertyAccessor
Method represents a property accessor.