public bool CanRead(IEvaluationContext context, object target, string name) { if (target == null) { return(false); } var type = target is Type ? (Type)target : target.GetType(); if (type.IsArray && name.Equals("Length")) { return(true); } var cacheKey = new PropertyCacheKey(type, name, target is Type); if (_readerCache.ContainsKey(cacheKey)) { return(true); } var method = FindGetterForProperty(name, type, target); if (method != null) { // Treat it like a property... // The readerCache will only contain gettable properties (let's not worry about setters for now). var typeDescriptor = method.ReturnType; method = ClassUtils.GetInterfaceMethodIfPossible(method); _readerCache[cacheKey] = new InvokerPair(method, typeDescriptor); _typeDescriptorCache[cacheKey] = typeDescriptor; return(true); } else { var field = FindField(name, type, target); if (field != null) { var typeDescriptor = field.FieldType; _readerCache[cacheKey] = new InvokerPair(field, typeDescriptor); _typeDescriptorCache[cacheKey] = typeDescriptor; return(true); } } return(false); }
public ITypedValue Read(IEvaluationContext context, object target, string name) { if (target == null) { throw new ArgumentNullException(nameof(target)); } var type = target is Type ? (Type)target : target.GetType(); if (type.IsArray && name.Equals("Length")) { if (target is Type) { throw new AccessException("Cannot access length on array class itself"); } var asArray = (Array)target; return(new TypedValue(asArray.GetLength(0))); } var cacheKey = new PropertyCacheKey(type, name, target is Type); _readerCache.TryGetValue(cacheKey, out var invoker); _lastReadInvokerPair = invoker; if (invoker == null || invoker.Member is MethodInfo) { var method = (MethodInfo)(invoker != null ? invoker.Member : null); if (method == null) { method = FindGetterForProperty(name, type, target); if (method != null) { // Treat it like a property... // The readerCache will only contain gettable properties (let's not worry about setters for now). var typeDescriptor = method.ReturnType; method = ClassUtils.GetInterfaceMethodIfPossible(method); invoker = new InvokerPair(method, typeDescriptor); _lastReadInvokerPair = invoker; _readerCache[cacheKey] = invoker; } } if (method != null) { try { var value = method.Invoke(target, new object[0]); return(new TypedValue(value, value != null ? value.GetType() : invoker.TypeDescriptor)); } catch (Exception ex) { throw new AccessException("Unable to access property '" + name + "' through getter method", ex); } } } if (invoker == null || invoker.Member is FieldInfo) { var field = (FieldInfo)(invoker == null ? null : invoker.Member); if (field == null) { field = FindField(name, type, target); if (field != null) { invoker = new InvokerPair(field, field.FieldType); _lastReadInvokerPair = invoker; _readerCache[cacheKey] = invoker; } } if (field != null) { try { var value = field.GetValue(target); return(new TypedValue(value, value != null ? value.GetType() : invoker.TypeDescriptor)); } catch (Exception ex) { throw new AccessException("Unable to access field '" + name + "'", ex); } } } throw new AccessException("Neither getter method nor field found for property '" + name + "'"); }
public OptimalPropertyAccessor(InvokerPair target) { _member = target.Member; _typeDescriptor = target.TypeDescriptor; }
public IPropertyAccessor CreateOptimalAccessor(IEvaluationContext context, object target, string name) { // Don't be clever for arrays or a null target... if (target == null) { return(this); } var clazz = target is Type ? (Type)target : target.GetType(); if (clazz.IsArray) { return(this); } var cacheKey = new PropertyCacheKey(clazz, name, target is Type); _readerCache.TryGetValue(cacheKey, out var invocationTarget); if (invocationTarget == null || invocationTarget.Member is MethodInfo) { var method = (MethodInfo)invocationTarget?.Member; if (method == null) { method = FindGetterForProperty(name, clazz, target); if (method != null) { var typeDescriptor = method.ReturnType; method = ClassUtils.GetInterfaceMethodIfPossible(method); invocationTarget = new InvokerPair(method, typeDescriptor); _readerCache[cacheKey] = invocationTarget; } } if (method != null) { return(new OptimalPropertyAccessor(invocationTarget)); } } if (invocationTarget == null || invocationTarget.Member is FieldInfo) { var field = invocationTarget != null ? (FieldInfo)invocationTarget.Member : null; if (field == null) { field = FindField(name, clazz, target is Type); if (field != null) { invocationTarget = new InvokerPair(field, field.FieldType); _readerCache[cacheKey] = invocationTarget; } } if (field != null) { return(new OptimalPropertyAccessor(invocationTarget)); } } return(this); }