2using System.Reflection;
3using System.Reflection.Emit;
8#if FIRST_PASS == false && EXPORTER == false && IMPORTER == false
13 internal abstract class PropertyAccessor
28 this.type = type ??
throw new ArgumentNullException(nameof(type));
29 this.name = name ??
throw new ArgumentNullException(nameof(name));
40 protected string Name => name;
45 protected PropertyInfo Property => AccessorUtil.LazyGet(
ref property, () => type.GetProperty(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) ??
throw new InvalidOperationException();
53 internal sealed class PropertyAccessor<TProperty> : PropertyAccessor
64 public static PropertyAccessor<TProperty> LazyGet(
ref PropertyAccessor<TProperty> location,
Type type,
string name)
66 return AccessorUtil.LazyGet(
ref location, () =>
new PropertyAccessor<TProperty>(type, name));
69 Func<TProperty> getter;
70 Action<TProperty> setter;
86 Func<TProperty> Getter => AccessorUtil.LazyGet(
ref getter, MakeGetter);
91 Action<TProperty> Setter => AccessorUtil.LazyGet(
ref setter, MakeSetter);
98 Func<TProperty> MakeGetter()
101 throw new NotImplementedException();
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);
106 il.Emit(Property.GetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, Property.GetMethod);
107 il.Emit(OpCodes.Ret);
110 return (Func<TProperty>)dm.CreateDelegate(typeof(Func<TProperty>));
119 Action<TProperty> MakeSetter()
122 throw new NotImplementedException();
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);
127 il.Emit(OpCodes.Ldarg_0);
128 il.Emit(Property.SetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, Property.SetMethod);
129 il.Emit(OpCodes.Ret);
132 return (Action<TProperty>)dm.CreateDelegate(typeof(Action<TProperty>));
140 public TProperty GetValue() => Getter();
146 public void SetValue(TProperty value) => Setter(value);
155 internal sealed class PropertyAccessor<TObject, TProperty> : PropertyAccessor
165 public static PropertyAccessor<TObject, TProperty> LazyGet(
ref PropertyAccessor<TObject, TProperty> location,
Type type,
string name)
167 return AccessorUtil.LazyGet(
ref location, () =>
new PropertyAccessor<TObject, TProperty>(type, name));
170 Func<TObject, TProperty> getter;
171 Action<TObject, TProperty> setter;
187 Func<TObject, TProperty> Getter => AccessorUtil.LazyGet(
ref getter, MakeGetter);
192 Action<TObject, TProperty> Setter => AccessorUtil.LazyGet(
ref setter, MakeSetter);
198 Func<TObject, TProperty> MakeGetter()
200#if FIRST_PASS || IMPORTER || EXPORTER
201 throw new NotImplementedException();
203 if (Property.CanRead ==
false)
204 throw new InternalException($
"Property {Property.Name} cannot be read.");
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);
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);
215 return (Func<TObject, TProperty>)dm.CreateDelegate(typeof(Func<TObject, TProperty>));
223 Action<TObject, TProperty> MakeSetter()
225#if FIRST_PASS || IMPORTER || EXPORTER
226 throw new NotImplementedException();
228 if (Property.CanWrite ==
false)
229 throw new InternalException($
"Property {Property.Name} cannot be written.");
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);
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);
241 return (Action<TObject, TProperty>)dm.CreateDelegate(typeof(Action<TObject, TProperty>));
250 public TProperty GetValue(TObject
self) => Getter(
self);
257 public void SetValue(TObject
self, TProperty value) => Setter(
self, value);
IKVM.Reflection.Type Type
IKVM.Reflection.PropertyInfo PropertyInfo
global::java.lang.invoke.LambdaForm.Name Name
@ PropertyAccessor
Method represents a property accessor.