コード例 #1
0
        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);
        }
コード例 #2
0
        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 + "'");
        }
コード例 #3
0
 public OptimalPropertyAccessor(InvokerPair target)
 {
     _member         = target.Member;
     _typeDescriptor = target.TypeDescriptor;
 }
コード例 #4
0
        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);
        }