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); }
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); }
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)); }
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); }
/// <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)); }
public static FastProperty GetProperty <T>( Expression <Func <T, object> > property, PropertyCachingStrategy cachingStrategy = PropertyCachingStrategy.Cached) { return(GetProperty(property.ExtractPropertyInfo(), cachingStrategy)); }
/// <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())); }
/// <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); } }
/// <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); }