Пример #1
0
        public static FastProperty GetProperty(
            Type type,
            string propertyName,
            PropertyCachingStrategy cachingStrategy = PropertyCachingStrategy.Cached)
        {
            Guard.NotNull(type, nameof(type));
            Guard.NotEmpty(propertyName, nameof(propertyName));

            FastProperty fastProperty = null;

            if (TryGetCachedProperty(type, propertyName, cachingStrategy == PropertyCachingStrategy.EagerCached, out fastProperty))
            {
                return(fastProperty);
            }

            var key = new PropertyKey(type, propertyName);

            if (!_singlePropertiesCache.TryGetValue(key, out fastProperty))
            {
                var pi = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase);
                if (pi != null)
                {
                    fastProperty = CreateInstance(pi);
                    if (cachingStrategy > PropertyCachingStrategy.Uncached)
                    {
                        _singlePropertiesCache.TryAdd(key, fastProperty);
                    }
                }
            }

            return(fastProperty);
        }
Пример #2
0
        public static FastProperty GetProperty(
            PropertyInfo propertyInfo,
            PropertyCachingStrategy cachingStrategy = PropertyCachingStrategy.Cached)
        {
            Guard.NotNull(propertyInfo, nameof(propertyInfo));

            FastProperty fastProperty = null;

            if (TryGetCachedProperty(propertyInfo.ReflectedType, propertyInfo.Name, cachingStrategy == PropertyCachingStrategy.EagerCached, out fastProperty))
            {
                return(fastProperty);
            }

            var key = new PropertyKey(propertyInfo.ReflectedType, propertyInfo.Name);

            if (!_singlePropertiesCache.TryGetValue(key, out fastProperty))
            {
                fastProperty = CreateInstance(propertyInfo);
                if (cachingStrategy > PropertyCachingStrategy.Uncached)
                {
                    _singlePropertiesCache.TryAdd(key, fastProperty);
                }
            }

            return(fastProperty);
        }
Пример #3
0
        public static FastPropertyInvoker <T, TProp> CompileFast <T, TProp>(
            this Expression <Func <T, TProp> > expression,
            PropertyCachingStrategy cachingStrategy = PropertyCachingStrategy.Cached)
        {
            if (!(expression.Body is MemberExpression member))
            {
                throw new ArgumentException($"Expression body must refer to a property.", nameof(expression));
            }

            if (!(member.Member is PropertyInfo pi))
            {
                throw new ArgumentException($"Expression body member must refer to a property.", nameof(expression));
            }

            var fastProp = FastProperty.GetProperty(pi, cachingStrategy);

            return(new FastPropertyInvoker <T, TProp>(fastProp));
        }
Пример #4
0
        public static FastProperty GetProperty(
            Type type,
            string propertyName,
            PropertyCachingStrategy cachingStrategy = PropertyCachingStrategy.Cached)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }
            if (string.IsNullOrEmpty(propertyName))
            {
                throw new Exception(nameof(propertyName));
            }

            FastProperty fastProperty = null;

            if (TryGetCachedProperty(type, propertyName, cachingStrategy == PropertyCachingStrategy.EagerCached, out fastProperty))
            {
                return(fastProperty);
            }

            var key = new PropertyKey(type, propertyName);

            if (!_singlePropertiesCache.TryGetValue(key, out fastProperty))
            {
                var pi = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase);
                if (pi != null)
                {
                    fastProperty = CreateInstance(pi);
                    if (cachingStrategy > PropertyCachingStrategy.Uncached)
                    {
                        _singlePropertiesCache.TryAdd(key, fastProperty);
                    }
                }
            }

            return(fastProperty);
        }
Пример #5
0
        /// <summary>
        /// <para>
        /// Creates and caches fast property helpers that expose getters for every non-hidden get property
        /// on the specified type.
        /// </para>
        /// <para>
        /// <see cref="GetVisibleProperties(Type, PropertyCachingStrategy)"/> excludes properties defined on base types that have been
        /// hidden by definitions using the <c>new</c> keyword.
        /// </para>
        /// </summary>
        /// <param name="type">The type to extract property accessors for.</param>
        /// <returns>
        /// A cached array of all public property getters from the type.
        /// </returns>
        public static IReadOnlyDictionary <string, FastProperty> GetVisibleProperties(Type type, PropertyCachingStrategy cachingStrategy = PropertyCachingStrategy.Cached)
        {
            var propertiesCache        = cachingStrategy > PropertyCachingStrategy.Uncached ? _propertiesCache : CreateVolatileCache();
            var visiblePropertiesCache = cachingStrategy > PropertyCachingStrategy.Uncached ? _visiblePropertiesCache : CreateVolatileCache();

            return((IReadOnlyDictionary <string, FastProperty>)GetVisibleProperties(type, CreateInstance, propertiesCache, visiblePropertiesCache));
        }
Пример #6
0
 public static FastProperty GetProperty <T>(
     Expression <Func <T, object> > property,
     PropertyCachingStrategy cachingStrategy = PropertyCachingStrategy.Cached)
 {
     return(GetProperty(property.ExtractPropertyInfo(), cachingStrategy));
 }
Пример #7
0
 /// <summary>
 /// Creates and caches fast property helpers that expose getters for every public get property on the
 /// underlying type.
 /// </summary>
 /// <param name="instance">the instance to extract property accessors for.</param>
 /// <returns>A cached array of all public property getters from the underlying type of target instance.
 /// </returns>
 public static IReadOnlyDictionary <string, FastProperty> GetProperties(object instance, PropertyCachingStrategy cachingStrategy = PropertyCachingStrategy.Cached)
 {
     return(GetProperties(instance.GetType()));
 }
Пример #8
0
        /// <summary>
        /// Creates and caches fast property helpers that expose getters for every public get property on the
        /// specified type.
        /// </summary>
        /// <param name="type">The type to extract property accessors for.</param>
        /// <returns>A cached array of all public property getters from the type of target instance.
        /// </returns>
        public static IReadOnlyDictionary <string, FastProperty> GetProperties(Type type, PropertyCachingStrategy cachingStrategy = PropertyCachingStrategy.Cached)
        {
            Guard.NotNull(type, nameof(type));

            // Unwrap nullable types. This means Nullable<T>.Value and Nullable<T>.HasValue will not be
            // part of the sequence of properties returned by this method.
            type = Nullable.GetUnderlyingType(type) ?? type;

            if (!_propertiesCache.TryGetValue(type, out var props))
            {
                if (cachingStrategy == PropertyCachingStrategy.Uncached)
                {
                    props = Get(type);
                }
                else
                {
                    props = _propertiesCache.GetOrAdd(type, Get);
                }
            }

            return((IReadOnlyDictionary <string, FastProperty>)props);

            IDictionary <string, FastProperty> Get(Type t)
            {
                var candidates     = GetCandidateProperties(t);
                var fastProperties = candidates.Select(p => Create(p)).ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase);

                CleanDuplicates(t, fastProperties.Keys);
                return(fastProperties);
            }
        }
Пример #9
0
        /// <summary>
        /// <para>
        /// Creates and caches fast property helpers that expose getters for every non-hidden get property
        /// on the specified type.
        /// </para>
        /// <para>
        /// <see cref="GetVisibleProperties(Type, PropertyCachingStrategy)"/> excludes properties defined on base types that have been
        /// hidden by definitions using the <c>new</c> keyword.
        /// </para>
        /// </summary>
        /// <param name="type">The type to extract property accessors for.</param>
        /// <returns>
        /// A cached array of all public property getters from the type.
        /// </returns>
        public static IReadOnlyDictionary <string, FastProperty> GetVisibleProperties(Type type, PropertyCachingStrategy cachingStrategy = PropertyCachingStrategy.Cached)
        {
            Guard.NotNull(type, nameof(type));

            // Unwrap nullable types. This means Nullable<T>.Value and Nullable<T>.HasValue will not be
            // part of the sequence of properties returned by this method.
            type = Nullable.GetUnderlyingType(type) ?? type;

            if (_visiblePropertiesCache.TryGetValue(type, out var result))
            {
                return((IReadOnlyDictionary <string, FastProperty>)result);
            }

            var visiblePropertiesCache = cachingStrategy > PropertyCachingStrategy.Uncached ? _visiblePropertiesCache : CreateVolatileCache();

            // The simple and common case, this is normal POCO object - no need to allocate.
            var allPropertiesDefinedOnType = true;
            var allProperties = GetProperties(type, cachingStrategy);

            foreach (var prop in allProperties.Values)
            {
                if (prop.Property.DeclaringType != type)
                {
                    allPropertiesDefinedOnType = false;
                    break;
                }
            }

            if (allPropertiesDefinedOnType)
            {
                result = (IDictionary <string, FastProperty>)allProperties;
                visiblePropertiesCache.TryAdd(type, result);
                return(allProperties);
            }

            // There's some inherited properties here, so we need to check for hiding via 'new'.
            var filteredProperties = new List <FastProperty>(allProperties.Count);

            foreach (var prop in allProperties.Values)
            {
                var declaringType = prop.Property.DeclaringType;
                if (declaringType == type)
                {
                    filteredProperties.Add(prop);
                    continue;
                }

                // If this property was declared on a base type then look for the definition closest to the
                // the type to see if we should include it.
                var ignoreProperty = false;

                // Walk up the hierarchy until we find the type that actally declares this
                // PropertyInfo.
                var currentTypeInfo   = type.GetTypeInfo();
                var declaringTypeInfo = declaringType.GetTypeInfo();
                while (currentTypeInfo != null && currentTypeInfo != declaringTypeInfo)
                {
                    // We've found a 'more proximal' public definition
                    var declaredProperty = currentTypeInfo.GetDeclaredProperty(prop.Name);
                    if (declaredProperty != null)
                    {
                        ignoreProperty = true;
                        break;
                    }

                    if (currentTypeInfo.BaseType != null)
                    {
                        currentTypeInfo = currentTypeInfo.BaseType.GetTypeInfo();
                    }
                }

                if (!ignoreProperty)
                {
                    filteredProperties.Add(prop);
                }
            }

            result = filteredProperties.ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase);
            visiblePropertiesCache.TryAdd(type, result);
            return((IReadOnlyDictionary <string, FastProperty>)result);
        }