coding styles nullable
This commit is contained in:
@@ -1,188 +1,161 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Swan.Reflection
|
||||
{
|
||||
namespace Swan.Reflection {
|
||||
/// <summary>
|
||||
/// A thread-safe cache of attributes belonging to a given key (MemberInfo or Type).
|
||||
///
|
||||
/// The Retrieve method is the most useful one in this class as it
|
||||
/// calls the retrieval process if the type is not contained
|
||||
/// in the cache.
|
||||
/// </summary>
|
||||
public class AttributeCache {
|
||||
private readonly Lazy<ConcurrentDictionary<Tuple<Object, Type>, IEnumerable<Object>>> _data = new Lazy<ConcurrentDictionary<Tuple<Object, Type>, IEnumerable<Object>>>(() => new ConcurrentDictionary<Tuple<Object, Type>, IEnumerable<Object>>(), true);
|
||||
|
||||
/// <summary>
|
||||
/// A thread-safe cache of attributes belonging to a given key (MemberInfo or Type).
|
||||
///
|
||||
/// The Retrieve method is the most useful one in this class as it
|
||||
/// calls the retrieval process if the type is not contained
|
||||
/// in the cache.
|
||||
/// Initializes a new instance of the <see cref="AttributeCache"/> class.
|
||||
/// </summary>
|
||||
public class AttributeCache
|
||||
{
|
||||
private readonly Lazy<ConcurrentDictionary<Tuple<object, Type>, IEnumerable<object>>> _data =
|
||||
new Lazy<ConcurrentDictionary<Tuple<object, Type>, IEnumerable<object>>>(() =>
|
||||
new ConcurrentDictionary<Tuple<object, Type>, IEnumerable<object>>(), true);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AttributeCache"/> class.
|
||||
/// </summary>
|
||||
/// <param name="propertyCache">The property cache object.</param>
|
||||
public AttributeCache(PropertyTypeCache? propertyCache = null)
|
||||
{
|
||||
PropertyTypeCache = propertyCache ?? PropertyTypeCache.DefaultCache.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default cache.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default cache.
|
||||
/// </value>
|
||||
public static Lazy<AttributeCache> DefaultCache { get; } = new Lazy<AttributeCache>(() => new AttributeCache());
|
||||
|
||||
/// <summary>
|
||||
/// A PropertyTypeCache object for caching properties and their attributes.
|
||||
/// </summary>
|
||||
public PropertyTypeCache PropertyTypeCache { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [contains] [the specified member].
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the attribute to be retrieved.</typeparam>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if [contains] [the specified member]; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool Contains<T>(MemberInfo member) => _data.Value.ContainsKey(new Tuple<object, Type>(member, typeof(T)));
|
||||
|
||||
/// <summary>
|
||||
/// Gets specific attributes from a member constrained to an attribute.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the attribute to be retrieved.</typeparam>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>An array of the attributes stored for the specified type.</returns>
|
||||
public IEnumerable<object> Retrieve<T>(MemberInfo member, bool inherit = false)
|
||||
where T : Attribute
|
||||
{
|
||||
if (member == null)
|
||||
throw new ArgumentNullException(nameof(member));
|
||||
|
||||
return Retrieve(new Tuple<object, Type>(member, typeof(T)), t => member.GetCustomAttributes<T>(inherit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all attributes of a specific type from a member.
|
||||
/// </summary>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <param name="type">The attribute type.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>An array of the attributes stored for the specified type.</returns>
|
||||
public IEnumerable<object> Retrieve(MemberInfo member, Type type, bool inherit = false)
|
||||
{
|
||||
if (member == null)
|
||||
throw new ArgumentNullException(nameof(member));
|
||||
|
||||
if (type == null)
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
|
||||
return Retrieve(
|
||||
new Tuple<object, Type>(member, type),
|
||||
t => member.GetCustomAttributes(type, inherit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets one attribute of a specific type from a member.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The attribute type.</typeparam>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>An attribute stored for the specified type.</returns>
|
||||
public T RetrieveOne<T>(MemberInfo member, bool inherit = false)
|
||||
where T : Attribute
|
||||
{
|
||||
if (member == null)
|
||||
return default;
|
||||
|
||||
var attr = Retrieve(
|
||||
new Tuple<object, Type>(member, typeof(T)),
|
||||
t => member.GetCustomAttributes(typeof(T), inherit));
|
||||
|
||||
return ConvertToAttribute<T>(attr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets one attribute of a specific type from a generic type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TAttribute">The type of the attribute.</typeparam>
|
||||
/// <typeparam name="T">The type to retrieve the attribute.</typeparam>
|
||||
/// <param name="inherit">if set to <c>true</c> [inherit].</param>
|
||||
/// <returns>An attribute stored for the specified type.</returns>
|
||||
public TAttribute RetrieveOne<TAttribute, T>(bool inherit = false)
|
||||
where TAttribute : Attribute
|
||||
{
|
||||
var attr = Retrieve(
|
||||
new Tuple<object, Type>(typeof(T), typeof(TAttribute)),
|
||||
t => typeof(T).GetCustomAttributes(typeof(TAttribute), inherit));
|
||||
|
||||
return ConvertToAttribute<TAttribute>(attr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all properties an their attributes of a given type constrained to only attributes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the attribute to retrieve.</typeparam>
|
||||
/// <param name="type">The type of the object.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>A dictionary of the properties and their attributes stored for the specified type.</returns>
|
||||
public Dictionary<PropertyInfo, IEnumerable<object>> Retrieve<T>(Type type, bool inherit = false)
|
||||
where T : Attribute =>
|
||||
PropertyTypeCache.RetrieveAllProperties(type, true)
|
||||
.ToDictionary(x => x, x => Retrieve<T>(x, inherit));
|
||||
|
||||
/// <summary>
|
||||
/// Gets all properties and their attributes of a given type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The object type used to extract the properties from.</typeparam>
|
||||
/// <typeparam name="TAttribute">The type of the attribute.</typeparam>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>
|
||||
/// A dictionary of the properties and their attributes stored for the specified type.
|
||||
/// </returns>
|
||||
public Dictionary<PropertyInfo, IEnumerable<object>> RetrieveFromType<T, TAttribute>(bool inherit = false)
|
||||
=> RetrieveFromType<T>(typeof(TAttribute), inherit);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all properties and their attributes of a given type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The object type used to extract the properties from.</typeparam>
|
||||
/// <param name="attributeType">Type of the attribute.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>
|
||||
/// A dictionary of the properties and their attributes stored for the specified type.
|
||||
/// </returns>
|
||||
public Dictionary<PropertyInfo, IEnumerable<object>> RetrieveFromType<T>(Type attributeType, bool inherit = false)
|
||||
{
|
||||
if (attributeType == null)
|
||||
throw new ArgumentNullException(nameof(attributeType));
|
||||
|
||||
return PropertyTypeCache.RetrieveAllProperties<T>(true)
|
||||
.ToDictionary(x => x, x => Retrieve(x, attributeType, inherit));
|
||||
}
|
||||
|
||||
private static T ConvertToAttribute<T>(IEnumerable<object> attr)
|
||||
where T : Attribute
|
||||
{
|
||||
if (attr?.Any() != true)
|
||||
return default;
|
||||
|
||||
return attr.Count() == 1
|
||||
? (T) Convert.ChangeType(attr.First(), typeof(T))
|
||||
: throw new AmbiguousMatchException("Multiple custom attributes of the same type found.");
|
||||
}
|
||||
|
||||
private IEnumerable<object> Retrieve(Tuple<object, Type> key, Func<Tuple<object, Type>, IEnumerable<object>> factory)
|
||||
{
|
||||
if (factory == null)
|
||||
throw new ArgumentNullException(nameof(factory));
|
||||
|
||||
return _data.Value.GetOrAdd(key, k => factory.Invoke(k).Where(item => item != null));
|
||||
}
|
||||
}
|
||||
/// <param name="propertyCache">The property cache object.</param>
|
||||
public AttributeCache(PropertyTypeCache? propertyCache = null) => this.PropertyTypeCache = propertyCache ?? PropertyTypeCache.DefaultCache.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default cache.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default cache.
|
||||
/// </value>
|
||||
public static Lazy<AttributeCache> DefaultCache { get; } = new Lazy<AttributeCache>(() => new AttributeCache());
|
||||
|
||||
/// <summary>
|
||||
/// A PropertyTypeCache object for caching properties and their attributes.
|
||||
/// </summary>
|
||||
public PropertyTypeCache PropertyTypeCache {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [contains] [the specified member].
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the attribute to be retrieved.</typeparam>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if [contains] [the specified member]; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public Boolean Contains<T>(MemberInfo member) => this._data.Value.ContainsKey(new Tuple<Object, Type>(member, typeof(T)));
|
||||
|
||||
/// <summary>
|
||||
/// Gets specific attributes from a member constrained to an attribute.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the attribute to be retrieved.</typeparam>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>An array of the attributes stored for the specified type.</returns>
|
||||
public IEnumerable<Object> Retrieve<T>(MemberInfo member, Boolean inherit = false) where T : Attribute {
|
||||
if(member == null) {
|
||||
throw new ArgumentNullException(nameof(member));
|
||||
}
|
||||
|
||||
return this.Retrieve(new Tuple<Object, Type>(member, typeof(T)), t => member.GetCustomAttributes<T>(inherit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all attributes of a specific type from a member.
|
||||
/// </summary>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <param name="type">The attribute type.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>An array of the attributes stored for the specified type.</returns>
|
||||
public IEnumerable<Object> Retrieve(MemberInfo member, Type type, Boolean inherit = false) {
|
||||
if(member == null) {
|
||||
throw new ArgumentNullException(nameof(member));
|
||||
}
|
||||
|
||||
if(type == null) {
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
return this.Retrieve(new Tuple<Object, Type>(member, type), t => member.GetCustomAttributes(type, inherit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets one attribute of a specific type from a member.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The attribute type.</typeparam>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>An attribute stored for the specified type.</returns>
|
||||
public T RetrieveOne<T>(MemberInfo member, Boolean inherit = false) where T : Attribute {
|
||||
if(member == null) {
|
||||
return default!;
|
||||
}
|
||||
|
||||
IEnumerable<Object> attr = this.Retrieve(new Tuple<Object, Type>(member, typeof(T)), t => member.GetCustomAttributes(typeof(T), inherit));
|
||||
|
||||
return ConvertToAttribute<T>(attr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets one attribute of a specific type from a generic type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TAttribute">The type of the attribute.</typeparam>
|
||||
/// <typeparam name="T">The type to retrieve the attribute.</typeparam>
|
||||
/// <param name="inherit">if set to <c>true</c> [inherit].</param>
|
||||
/// <returns>An attribute stored for the specified type.</returns>
|
||||
public TAttribute RetrieveOne<TAttribute, T>(Boolean inherit = false) where TAttribute : Attribute {
|
||||
IEnumerable<Object> attr = this.Retrieve(new Tuple<Object, Type>(typeof(T), typeof(TAttribute)), t => typeof(T).GetCustomAttributes(typeof(TAttribute), inherit));
|
||||
|
||||
return ConvertToAttribute<TAttribute>(attr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all properties an their attributes of a given type constrained to only attributes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the attribute to retrieve.</typeparam>
|
||||
/// <param name="type">The type of the object.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>A dictionary of the properties and their attributes stored for the specified type.</returns>
|
||||
public Dictionary<PropertyInfo, IEnumerable<Object>> Retrieve<T>(Type type, Boolean inherit = false) where T : Attribute => this.PropertyTypeCache.RetrieveAllProperties(type, true).ToDictionary(x => x, x => this.Retrieve<T>(x, inherit));
|
||||
|
||||
/// <summary>
|
||||
/// Gets all properties and their attributes of a given type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The object type used to extract the properties from.</typeparam>
|
||||
/// <typeparam name="TAttribute">The type of the attribute.</typeparam>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>
|
||||
/// A dictionary of the properties and their attributes stored for the specified type.
|
||||
/// </returns>
|
||||
public Dictionary<PropertyInfo, IEnumerable<Object>> RetrieveFromType<T, TAttribute>(Boolean inherit = false) => this.RetrieveFromType<T>(typeof(TAttribute), inherit);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all properties and their attributes of a given type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The object type used to extract the properties from.</typeparam>
|
||||
/// <param name="attributeType">Type of the attribute.</param>
|
||||
/// <param name="inherit"><c>true</c> to inspect the ancestors of element; otherwise, <c>false</c>.</param>
|
||||
/// <returns>
|
||||
/// A dictionary of the properties and their attributes stored for the specified type.
|
||||
/// </returns>
|
||||
public Dictionary<PropertyInfo, IEnumerable<Object>> RetrieveFromType<T>(Type attributeType, Boolean inherit = false) {
|
||||
if(attributeType == null) {
|
||||
throw new ArgumentNullException(nameof(attributeType));
|
||||
}
|
||||
|
||||
return this.PropertyTypeCache.RetrieveAllProperties<T>(true).ToDictionary(x => x, x => this.Retrieve(x, attributeType, inherit));
|
||||
}
|
||||
|
||||
private static T ConvertToAttribute<T>(IEnumerable<Object> attr) where T : Attribute => attr?.Any() != true ? (default!) : attr.Count() == 1 ? (T)Convert.ChangeType(attr.First(), typeof(T)) : throw new AmbiguousMatchException("Multiple custom attributes of the same type found.");
|
||||
|
||||
private IEnumerable<Object> Retrieve(Tuple<Object, Type> key, Func<Tuple<Object, Type>, IEnumerable<Object>> factory) {
|
||||
if(factory == null) {
|
||||
throw new ArgumentNullException(nameof(factory));
|
||||
}
|
||||
|
||||
return this._data.Value.GetOrAdd(key, k => factory.Invoke(k).Where(item => item != null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,48 +4,39 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Swan.Lite.Reflection
|
||||
{
|
||||
namespace Swan.Lite.Reflection {
|
||||
/// <summary>
|
||||
/// A thread-safe cache of constructors belonging to a given type.
|
||||
/// </summary>
|
||||
public class ConstructorTypeCache : TypeCache<Tuple<ConstructorInfo, ParameterInfo[]>> {
|
||||
/// <summary>
|
||||
/// A thread-safe cache of constructors belonging to a given type.
|
||||
/// Gets the default cache.
|
||||
/// </summary>
|
||||
public class ConstructorTypeCache : TypeCache<Tuple<ConstructorInfo, ParameterInfo[]>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the default cache.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default cache.
|
||||
/// </value>
|
||||
public static Lazy<ConstructorTypeCache> DefaultCache { get; } =
|
||||
new Lazy<ConstructorTypeCache>(() => new ConstructorTypeCache());
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all constructors order by the number of parameters ascending.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to inspect.</typeparam>
|
||||
/// <param name="includeNonPublic">if set to <c>true</c> [include non public].</param>
|
||||
/// <returns>
|
||||
/// A collection with all the constructors in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<Tuple<ConstructorInfo, ParameterInfo[]>> RetrieveAllConstructors<T>(bool includeNonPublic = false)
|
||||
=> Retrieve<T>(GetConstructors(includeNonPublic));
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all constructors order by the number of parameters ascending.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="includeNonPublic">if set to <c>true</c> [include non public].</param>
|
||||
/// <returns>
|
||||
/// A collection with all the constructors in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<Tuple<ConstructorInfo, ParameterInfo[]>> RetrieveAllConstructors(Type type, bool includeNonPublic = false)
|
||||
=> Retrieve(type, GetConstructors(includeNonPublic));
|
||||
|
||||
private static Func<Type, IEnumerable<Tuple<ConstructorInfo, ParameterInfo[]>>> GetConstructors(bool includeNonPublic)
|
||||
=> t => t.GetConstructors(includeNonPublic ? BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance : BindingFlags.Public | BindingFlags.Instance)
|
||||
.Select(x => Tuple.Create(x, x.GetParameters()))
|
||||
.OrderBy(x => x.Item2.Length)
|
||||
.ToList();
|
||||
}
|
||||
/// <value>
|
||||
/// The default cache.
|
||||
/// </value>
|
||||
public static Lazy<ConstructorTypeCache> DefaultCache { get; } = new Lazy<ConstructorTypeCache>(() => new ConstructorTypeCache());
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all constructors order by the number of parameters ascending.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to inspect.</typeparam>
|
||||
/// <param name="includeNonPublic">if set to <c>true</c> [include non public].</param>
|
||||
/// <returns>
|
||||
/// A collection with all the constructors in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<Tuple<ConstructorInfo, ParameterInfo[]>> RetrieveAllConstructors<T>(Boolean includeNonPublic = false) => this.Retrieve<T>(GetConstructors(includeNonPublic));
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all constructors order by the number of parameters ascending.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="includeNonPublic">if set to <c>true</c> [include non public].</param>
|
||||
/// <returns>
|
||||
/// A collection with all the constructors in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<Tuple<ConstructorInfo, ParameterInfo[]>> RetrieveAllConstructors(Type type, Boolean includeNonPublic = false) => this.Retrieve(type, GetConstructors(includeNonPublic));
|
||||
|
||||
private static Func<Type, IEnumerable<Tuple<ConstructorInfo, ParameterInfo[]>>> GetConstructors(Boolean includeNonPublic) => t => t.GetConstructors(includeNonPublic ? BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance : BindingFlags.Public | BindingFlags.Instance).Select(x => Tuple.Create(x, x.GetParameters())).OrderBy(x => x.Item2.Length).ToList();
|
||||
}
|
||||
}
|
||||
@@ -2,106 +2,112 @@
|
||||
using System.Reflection;
|
||||
using Swan.Configuration;
|
||||
|
||||
namespace Swan.Reflection
|
||||
{
|
||||
namespace Swan.Reflection {
|
||||
/// <summary>
|
||||
/// Represents a Property object from a Object Reflection Property with extended values.
|
||||
/// </summary>
|
||||
public class ExtendedPropertyInfo {
|
||||
/// <summary>
|
||||
/// Represents a Property object from a Object Reflection Property with extended values.
|
||||
/// Initializes a new instance of the <see cref="ExtendedPropertyInfo"/> class.
|
||||
/// </summary>
|
||||
public class ExtendedPropertyInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExtendedPropertyInfo"/> class.
|
||||
/// </summary>
|
||||
/// <param name="propertyInfo">The property information.</param>
|
||||
public ExtendedPropertyInfo(PropertyInfo propertyInfo)
|
||||
{
|
||||
if (propertyInfo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(propertyInfo));
|
||||
}
|
||||
|
||||
Property = propertyInfo.Name;
|
||||
DataType = propertyInfo.PropertyType.Name;
|
||||
|
||||
foreach (PropertyDisplayAttribute display in AttributeCache.DefaultCache.Value.Retrieve<PropertyDisplayAttribute>(propertyInfo, true))
|
||||
{
|
||||
Name = display.Name;
|
||||
Description = display.Description;
|
||||
GroupName = display.GroupName;
|
||||
DefaultValue = display.DefaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the property.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The property.
|
||||
/// </value>
|
||||
public string Property { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the data.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of the data.
|
||||
/// </value>
|
||||
public string DataType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The value.
|
||||
/// </value>
|
||||
public object Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default value.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value.
|
||||
/// </value>
|
||||
public object DefaultValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name.
|
||||
/// </value>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The description.
|
||||
/// </value>
|
||||
public string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the group.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the group.
|
||||
/// </value>
|
||||
public string GroupName { get; }
|
||||
}
|
||||
|
||||
/// <param name="propertyInfo">The property information.</param>
|
||||
public ExtendedPropertyInfo(PropertyInfo propertyInfo) {
|
||||
if(propertyInfo == null) {
|
||||
throw new ArgumentNullException(nameof(propertyInfo));
|
||||
}
|
||||
|
||||
this.Property = propertyInfo.Name;
|
||||
this.DataType = propertyInfo.PropertyType.Name;
|
||||
|
||||
foreach(PropertyDisplayAttribute display in AttributeCache.DefaultCache.Value.Retrieve<PropertyDisplayAttribute>(propertyInfo, true)) {
|
||||
this.Name = display.Name;
|
||||
this.Description = display.Description;
|
||||
this.GroupName = display.GroupName;
|
||||
this.DefaultValue = display.DefaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Property object from a Object Reflection Property with extended values.
|
||||
/// Gets or sets the property.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the object.</typeparam>
|
||||
public class ExtendedPropertyInfo<T> : ExtendedPropertyInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExtendedPropertyInfo{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
public ExtendedPropertyInfo(string property)
|
||||
: base(typeof(T).GetProperty(property))
|
||||
{
|
||||
}
|
||||
}
|
||||
/// <value>
|
||||
/// The property.
|
||||
/// </value>
|
||||
public String Property {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the data.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of the data.
|
||||
/// </value>
|
||||
public String DataType {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The value.
|
||||
/// </value>
|
||||
public Object Value {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default value.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value.
|
||||
/// </value>
|
||||
public Object DefaultValue {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name.
|
||||
/// </value>
|
||||
public String Name {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The description.
|
||||
/// </value>
|
||||
public String Description {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the group.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the group.
|
||||
/// </value>
|
||||
public String GroupName {
|
||||
get;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Property object from a Object Reflection Property with extended values.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the object.</typeparam>
|
||||
public class ExtendedPropertyInfo<T> : ExtendedPropertyInfo {
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExtendedPropertyInfo{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
public ExtendedPropertyInfo(String property) : base(typeof(T).GetProperty(property)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,267 +1,247 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Swan.Reflection
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides extended information about a type.
|
||||
///
|
||||
/// This class is mainly used to define sets of types within the Definition class
|
||||
/// and it is not meant for other than querying the BasicTypesInfo dictionary.
|
||||
/// </summary>
|
||||
public class ExtendedTypeInfo
|
||||
namespace Swan.Reflection {
|
||||
/// <summary>
|
||||
/// Provides extended information about a type.
|
||||
///
|
||||
/// This class is mainly used to define sets of types within the Definition class
|
||||
/// and it is not meant for other than querying the BasicTypesInfo dictionary.
|
||||
/// </summary>
|
||||
public class ExtendedTypeInfo {
|
||||
private const String TryParseMethodName = nameof(Byte.TryParse);
|
||||
private const String ToStringMethodName = nameof(ToString);
|
||||
|
||||
private static readonly Type[] NumericTypes =
|
||||
{
|
||||
private const string TryParseMethodName = nameof(byte.TryParse);
|
||||
private const string ToStringMethodName = nameof(ToString);
|
||||
|
||||
private static readonly Type[] NumericTypes =
|
||||
{
|
||||
typeof(byte),
|
||||
typeof(sbyte),
|
||||
typeof(decimal),
|
||||
typeof(double),
|
||||
typeof(float),
|
||||
typeof(int),
|
||||
typeof(uint),
|
||||
typeof(long),
|
||||
typeof(ulong),
|
||||
typeof(short),
|
||||
typeof(ushort),
|
||||
};
|
||||
|
||||
private readonly ParameterInfo[]? _tryParseParameters;
|
||||
private readonly int _toStringArgumentLength;
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExtendedTypeInfo"/> class.
|
||||
/// </summary>
|
||||
/// <param name="t">The t.</param>
|
||||
public ExtendedTypeInfo(Type t)
|
||||
{
|
||||
Type = t ?? throw new ArgumentNullException(nameof(t));
|
||||
IsNullableValueType = Type.IsGenericType
|
||||
&& Type.GetGenericTypeDefinition() == typeof(Nullable<>);
|
||||
|
||||
IsValueType = t.IsValueType;
|
||||
|
||||
UnderlyingType = IsNullableValueType ?
|
||||
new NullableConverter(Type).UnderlyingType :
|
||||
Type;
|
||||
|
||||
IsNumeric = NumericTypes.Contains(UnderlyingType);
|
||||
|
||||
// Extract the TryParse method info
|
||||
try
|
||||
{
|
||||
TryParseMethodInfo = UnderlyingType.GetMethod(TryParseMethodName,
|
||||
new[] { typeof(string), typeof(NumberStyles), typeof(IFormatProvider), UnderlyingType.MakeByRefType() }) ??
|
||||
UnderlyingType.GetMethod(TryParseMethodName,
|
||||
new[] { typeof(string), UnderlyingType.MakeByRefType() });
|
||||
|
||||
_tryParseParameters = TryParseMethodInfo?.GetParameters();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
// Extract the ToString method Info
|
||||
try
|
||||
{
|
||||
ToStringMethodInfo = UnderlyingType.GetMethod(ToStringMethodName,
|
||||
new[] { typeof(IFormatProvider) }) ??
|
||||
UnderlyingType.GetMethod(ToStringMethodName,
|
||||
Array.Empty<Type>());
|
||||
|
||||
_toStringArgumentLength = ToStringMethodInfo?.GetParameters().Length ?? 0;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type this extended info class provides for.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type.
|
||||
/// </value>
|
||||
public Type Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the type is a nullable value type.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is nullable value type; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsNullableValueType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the type or underlying type is numeric.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is numeric; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsNumeric { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the type is value type.
|
||||
/// Nullable value types have this property set to False.
|
||||
/// </summary>
|
||||
public bool IsValueType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// When dealing with nullable value types, this property will
|
||||
/// return the underlying value type of the nullable,
|
||||
/// Otherwise it will return the same type as the Type property.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of the underlying.
|
||||
/// </value>
|
||||
public Type UnderlyingType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the try parse method information. If the type does not contain
|
||||
/// a suitable TryParse static method, it will return null.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The try parse method information.
|
||||
/// </value>
|
||||
public MethodInfo TryParseMethodInfo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ToString method info
|
||||
/// It will prefer the overload containing the IFormatProvider argument.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// To string method information.
|
||||
/// </value>
|
||||
public MethodInfo ToStringMethodInfo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the type contains a suitable TryParse method.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance can parse natively; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool CanParseNatively => TryParseMethodInfo != null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Tries to parse the string into an object of the type this instance represents.
|
||||
/// Returns false when no suitable TryParse methods exists for the type or when parsing fails
|
||||
/// for any reason. When possible, this method uses CultureInfo.InvariantCulture and NumberStyles.Any.
|
||||
/// </summary>
|
||||
/// <param name="s">The s.</param>
|
||||
/// <param name="result">The result.</param>
|
||||
/// <returns><c>true</c> if parse was converted successfully; otherwise, <c>false</c>.</returns>
|
||||
public bool TryParse(string s, out object? result)
|
||||
{
|
||||
result = Type.GetDefault();
|
||||
|
||||
try
|
||||
{
|
||||
if (Type == typeof(string))
|
||||
{
|
||||
result = Convert.ChangeType(s, Type, CultureInfo.InvariantCulture);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((IsNullableValueType && string.IsNullOrEmpty(s)) || !CanParseNatively)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Build the arguments of the TryParse method
|
||||
var dynamicArguments = new List<object?> { s };
|
||||
|
||||
for (var pi = 1; pi < _tryParseParameters.Length - 1; pi++)
|
||||
{
|
||||
var argInfo = _tryParseParameters[pi];
|
||||
if (argInfo.ParameterType == typeof(IFormatProvider))
|
||||
dynamicArguments.Add(CultureInfo.InvariantCulture);
|
||||
else if (argInfo.ParameterType == typeof(NumberStyles))
|
||||
dynamicArguments.Add(NumberStyles.Any);
|
||||
else
|
||||
dynamicArguments.Add(null);
|
||||
}
|
||||
|
||||
dynamicArguments.Add(null);
|
||||
var parseArguments = dynamicArguments.ToArray();
|
||||
|
||||
if ((bool) TryParseMethodInfo.Invoke(null, parseArguments))
|
||||
{
|
||||
result = parseArguments[parseArguments.Length - 1];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this instance to its string representation,
|
||||
/// trying to use the CultureInfo.InvariantCulture
|
||||
/// IFormat provider if the overload is available.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <returns>A <see cref="System.String" /> that represents the current object.</returns>
|
||||
public string ToStringInvariant(object instance)
|
||||
{
|
||||
if (instance == null)
|
||||
return string.Empty;
|
||||
|
||||
return _toStringArgumentLength != 1
|
||||
? instance.ToString()
|
||||
: ToStringMethodInfo.Invoke(instance, new object[] {CultureInfo.InvariantCulture}) as string ?? string.Empty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
typeof(Byte),
|
||||
typeof(SByte),
|
||||
typeof(Decimal),
|
||||
typeof(Double),
|
||||
typeof(Single),
|
||||
typeof(Int32),
|
||||
typeof(UInt32),
|
||||
typeof(Int64),
|
||||
typeof(UInt64),
|
||||
typeof(Int16),
|
||||
typeof(UInt16),
|
||||
};
|
||||
|
||||
private readonly ParameterInfo[]? _tryParseParameters;
|
||||
private readonly Int32 _toStringArgumentLength;
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Provides extended information about a type.
|
||||
///
|
||||
/// This class is mainly used to define sets of types within the Constants class
|
||||
/// and it is not meant for other than querying the BasicTypesInfo dictionary.
|
||||
/// Initializes a new instance of the <see cref="ExtendedTypeInfo"/> class.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of extended type information.</typeparam>
|
||||
public class ExtendedTypeInfo<T> : ExtendedTypeInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExtendedTypeInfo{T}"/> class.
|
||||
/// </summary>
|
||||
public ExtendedTypeInfo()
|
||||
: base(typeof(T))
|
||||
{
|
||||
// placeholder
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this instance to its string representation,
|
||||
/// trying to use the CultureInfo.InvariantCulture
|
||||
/// IFormat provider if the overload is available.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <returns>A <see cref="System.String" /> that represents the current object.</returns>
|
||||
public string ToStringInvariant(T instance) => base.ToStringInvariant(instance);
|
||||
}
|
||||
/// <param name="t">The t.</param>
|
||||
public ExtendedTypeInfo(Type t) {
|
||||
this.Type = t ?? throw new ArgumentNullException(nameof(t));
|
||||
this.IsNullableValueType = this.Type.IsGenericType && this.Type.GetGenericTypeDefinition() == typeof(Nullable<>);
|
||||
|
||||
this.IsValueType = t.IsValueType;
|
||||
|
||||
this.UnderlyingType = this.IsNullableValueType ? new NullableConverter(this.Type).UnderlyingType : this.Type;
|
||||
|
||||
this.IsNumeric = NumericTypes.Contains(this.UnderlyingType);
|
||||
|
||||
// Extract the TryParse method info
|
||||
try {
|
||||
this.TryParseMethodInfo = this.UnderlyingType.GetMethod(TryParseMethodName, new[] { typeof(String), typeof(NumberStyles), typeof(IFormatProvider), this.UnderlyingType.MakeByRefType() }) ?? this.UnderlyingType.GetMethod(TryParseMethodName, new[] { typeof(String), this.UnderlyingType.MakeByRefType() });
|
||||
|
||||
this._tryParseParameters = this.TryParseMethodInfo?.GetParameters();
|
||||
} catch {
|
||||
// ignored
|
||||
}
|
||||
|
||||
// Extract the ToString method Info
|
||||
try {
|
||||
this.ToStringMethodInfo = this.UnderlyingType.GetMethod(ToStringMethodName, new[] { typeof(IFormatProvider) }) ?? this.UnderlyingType.GetMethod(ToStringMethodName, Array.Empty<Type>());
|
||||
|
||||
this._toStringArgumentLength = this.ToStringMethodInfo?.GetParameters().Length ?? 0;
|
||||
} catch {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type this extended info class provides for.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type.
|
||||
/// </value>
|
||||
public Type Type {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the type is a nullable value type.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is nullable value type; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean IsNullableValueType {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the type or underlying type is numeric.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is numeric; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean IsNumeric {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the type is value type.
|
||||
/// Nullable value types have this property set to False.
|
||||
/// </summary>
|
||||
public Boolean IsValueType {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When dealing with nullable value types, this property will
|
||||
/// return the underlying value type of the nullable,
|
||||
/// Otherwise it will return the same type as the Type property.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of the underlying.
|
||||
/// </value>
|
||||
public Type UnderlyingType {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the try parse method information. If the type does not contain
|
||||
/// a suitable TryParse static method, it will return null.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The try parse method information.
|
||||
/// </value>
|
||||
public MethodInfo? TryParseMethodInfo {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ToString method info
|
||||
/// It will prefer the overload containing the IFormatProvider argument.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// To string method information.
|
||||
/// </value>
|
||||
public MethodInfo? ToStringMethodInfo {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the type contains a suitable TryParse method.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance can parse natively; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean CanParseNatively => this.TryParseMethodInfo != null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Tries to parse the string into an object of the type this instance represents.
|
||||
/// Returns false when no suitable TryParse methods exists for the type or when parsing fails
|
||||
/// for any reason. When possible, this method uses CultureInfo.InvariantCulture and NumberStyles.Any.
|
||||
/// </summary>
|
||||
/// <param name="s">The s.</param>
|
||||
/// <param name="result">The result.</param>
|
||||
/// <returns><c>true</c> if parse was converted successfully; otherwise, <c>false</c>.</returns>
|
||||
public Boolean TryParse(String s, out Object? result) {
|
||||
result = this.Type.GetDefault();
|
||||
|
||||
try {
|
||||
if(this.Type == typeof(String)) {
|
||||
result = Convert.ChangeType(s, this.Type, CultureInfo.InvariantCulture);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(this.IsNullableValueType && String.IsNullOrEmpty(s) || !this.CanParseNatively) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Build the arguments of the TryParse method
|
||||
List<Object?> dynamicArguments = new List<Object?> { s };
|
||||
if(this._tryParseParameters != null) {
|
||||
for(Int32 pi = 1; pi < this._tryParseParameters.Length - 1; pi++) {
|
||||
ParameterInfo argInfo = this._tryParseParameters[pi];
|
||||
if(argInfo.ParameterType == typeof(IFormatProvider)) {
|
||||
dynamicArguments.Add(CultureInfo.InvariantCulture);
|
||||
} else if(argInfo.ParameterType == typeof(NumberStyles)) {
|
||||
dynamicArguments.Add(NumberStyles.Any);
|
||||
} else {
|
||||
dynamicArguments.Add(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dynamicArguments.Add(null);
|
||||
Object?[] parseArguments = dynamicArguments.ToArray();
|
||||
|
||||
if((Boolean)this.TryParseMethodInfo?.Invoke(null, parseArguments)!) {
|
||||
result = parseArguments[^1];
|
||||
return true;
|
||||
}
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this instance to its string representation,
|
||||
/// trying to use the CultureInfo.InvariantCulture
|
||||
/// IFormat provider if the overload is available.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <returns>A <see cref="System.String" /> that represents the current object.</returns>
|
||||
public String ToStringInvariant(Object? instance) => instance == null ? String.Empty : this._toStringArgumentLength != 1 ? instance.ToString()! : this.ToStringMethodInfo?.Invoke(instance, new Object[] { CultureInfo.InvariantCulture }) as String ?? String.Empty;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides extended information about a type.
|
||||
///
|
||||
/// This class is mainly used to define sets of types within the Constants class
|
||||
/// and it is not meant for other than querying the BasicTypesInfo dictionary.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of extended type information.</typeparam>
|
||||
public class ExtendedTypeInfo<T> : ExtendedTypeInfo {
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExtendedTypeInfo{T}"/> class.
|
||||
/// </summary>
|
||||
public ExtendedTypeInfo() : base(typeof(T)) {
|
||||
// placeholder
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this instance to its string representation,
|
||||
/// trying to use the CultureInfo.InvariantCulture
|
||||
/// IFormat provider if the overload is available.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <returns>A <see cref="System.String" /> that represents the current object.</returns>
|
||||
public String ToStringInvariant(T instance) => base.ToStringInvariant(instance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
namespace Swan.Reflection
|
||||
{
|
||||
using System;
|
||||
|
||||
namespace Swan.Reflection {
|
||||
/// <summary>
|
||||
/// Represents a generic interface to store getters and setters.
|
||||
/// </summary>
|
||||
public interface IPropertyProxy {
|
||||
/// <summary>
|
||||
/// Represents a generic interface to store getters and setters.
|
||||
/// Gets the property value via a stored delegate.
|
||||
/// </summary>
|
||||
public interface IPropertyProxy
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the property value via a stored delegate.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <returns>The property value.</returns>
|
||||
object GetValue(object instance);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the property value via a stored delegate.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
void SetValue(object instance, object value);
|
||||
}
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <returns>The property value.</returns>
|
||||
Object GetValue(Object instance);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the property value via a stored delegate.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
void SetValue(Object instance, Object value);
|
||||
}
|
||||
}
|
||||
@@ -2,116 +2,109 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Swan.Reflection
|
||||
{
|
||||
namespace Swan.Reflection {
|
||||
/// <summary>
|
||||
/// Represents a Method Info Cache.
|
||||
/// </summary>
|
||||
public class MethodInfoCache : ConcurrentDictionary<String, MethodInfo> {
|
||||
/// <summary>
|
||||
/// Represents a Method Info Cache.
|
||||
/// Retrieves the properties stored for the specified type.
|
||||
/// If the properties are not available, it calls the factory method to retrieve them
|
||||
/// and returns them as an array of PropertyInfo.
|
||||
/// </summary>
|
||||
public class MethodInfoCache : ConcurrentDictionary<string, MethodInfo>
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves the properties stored for the specified type.
|
||||
/// If the properties are not available, it calls the factory method to retrieve them
|
||||
/// and returns them as an array of PropertyInfo.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of type.</typeparam>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="alias">The alias.</param>
|
||||
/// <param name="types">The types.</param>
|
||||
/// <returns>
|
||||
/// The cached MethodInfo.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">name
|
||||
/// or
|
||||
/// factory.</exception>
|
||||
public MethodInfo Retrieve<T>(string name, string alias, params Type[] types)
|
||||
=> Retrieve(typeof(T), name, alias, types);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the specified name.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of type.</typeparam>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="types">The types.</param>
|
||||
/// <returns>
|
||||
/// The cached MethodInfo.
|
||||
/// </returns>
|
||||
public MethodInfo Retrieve<T>(string name, params Type[] types)
|
||||
=> Retrieve(typeof(T), name, name, types);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the specified type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="types">The types.</param>
|
||||
/// <returns>
|
||||
/// An array of the properties stored for the specified type.
|
||||
/// </returns>
|
||||
public MethodInfo Retrieve(Type type, string name, params Type[] types)
|
||||
=> Retrieve(type, name, name, types);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the specified type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="alias">The alias.</param>
|
||||
/// <param name="types">The types.</param>
|
||||
/// <returns>
|
||||
/// The cached MethodInfo.
|
||||
/// </returns>
|
||||
public MethodInfo Retrieve(Type type, string name, string alias, params Type[] types)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
|
||||
if (alias == null)
|
||||
throw new ArgumentNullException(nameof(alias));
|
||||
|
||||
if (name == null)
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
|
||||
return GetOrAdd(
|
||||
alias,
|
||||
x => type.GetMethod(name, types ?? Array.Empty<Type>()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the specified name.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of type.</typeparam>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>
|
||||
/// The cached MethodInfo.
|
||||
/// </returns>
|
||||
public MethodInfo Retrieve<T>(string name)
|
||||
=> Retrieve(typeof(T), name);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the specified type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>
|
||||
/// The cached MethodInfo.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// type
|
||||
/// or
|
||||
/// name.
|
||||
/// </exception>
|
||||
public MethodInfo Retrieve(Type type, string name)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
|
||||
if (name == null)
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
|
||||
return GetOrAdd(
|
||||
name,
|
||||
type.GetMethod);
|
||||
}
|
||||
}
|
||||
/// <typeparam name="T">The type of type.</typeparam>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="alias">The alias.</param>
|
||||
/// <param name="types">The types.</param>
|
||||
/// <returns>
|
||||
/// The cached MethodInfo.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">name
|
||||
/// or
|
||||
/// factory.</exception>
|
||||
public MethodInfo Retrieve<T>(String name, String alias, params Type[] types) => this.Retrieve(typeof(T), name, alias, types);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the specified name.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of type.</typeparam>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="types">The types.</param>
|
||||
/// <returns>
|
||||
/// The cached MethodInfo.
|
||||
/// </returns>
|
||||
public MethodInfo Retrieve<T>(String name, params Type[] types) => this.Retrieve(typeof(T), name, name, types);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the specified type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="types">The types.</param>
|
||||
/// <returns>
|
||||
/// An array of the properties stored for the specified type.
|
||||
/// </returns>
|
||||
public MethodInfo Retrieve(Type type, String name, params Type[] types) => this.Retrieve(type, name, name, types);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the specified type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="alias">The alias.</param>
|
||||
/// <param name="types">The types.</param>
|
||||
/// <returns>
|
||||
/// The cached MethodInfo.
|
||||
/// </returns>
|
||||
public MethodInfo Retrieve(Type type, String name, String alias, params Type[] types) {
|
||||
if(type == null) {
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
if(alias == null) {
|
||||
throw new ArgumentNullException(nameof(alias));
|
||||
}
|
||||
|
||||
if(name == null) {
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
|
||||
return this.GetOrAdd(alias, x => type.GetMethod(name, types ?? Array.Empty<Type>()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the specified name.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of type.</typeparam>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>
|
||||
/// The cached MethodInfo.
|
||||
/// </returns>
|
||||
public MethodInfo Retrieve<T>(String name) => this.Retrieve(typeof(T), name);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the specified type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>
|
||||
/// The cached MethodInfo.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// type
|
||||
/// or
|
||||
/// name.
|
||||
/// </exception>
|
||||
public MethodInfo Retrieve(Type type, String name) {
|
||||
if(type == null) {
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
if(name == null) {
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
|
||||
return this.GetOrAdd(name, type.GetMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,46 +2,43 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Swan.Reflection
|
||||
{
|
||||
namespace Swan.Reflection {
|
||||
/// <summary>
|
||||
/// Represents a generic class to store getters and setters.
|
||||
/// </summary>
|
||||
/// <typeparam name="TClass">The type of the class.</typeparam>
|
||||
/// <typeparam name="TProperty">The type of the property.</typeparam>
|
||||
/// <seealso cref="IPropertyProxy" />
|
||||
public sealed class PropertyProxy<TClass, TProperty> : IPropertyProxy where TClass : class {
|
||||
private readonly Func<TClass, TProperty> _getter;
|
||||
private readonly Action<TClass, TProperty> _setter;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a generic class to store getters and setters.
|
||||
/// Initializes a new instance of the <see cref="PropertyProxy{TClass, TProperty}"/> class.
|
||||
/// </summary>
|
||||
/// <typeparam name="TClass">The type of the class.</typeparam>
|
||||
/// <typeparam name="TProperty">The type of the property.</typeparam>
|
||||
/// <seealso cref="IPropertyProxy" />
|
||||
public sealed class PropertyProxy<TClass, TProperty> : IPropertyProxy
|
||||
where TClass : class
|
||||
{
|
||||
private readonly Func<TClass, TProperty> _getter;
|
||||
private readonly Action<TClass, TProperty> _setter;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PropertyProxy{TClass, TProperty}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
public PropertyProxy(PropertyInfo property)
|
||||
{
|
||||
if (property == null)
|
||||
throw new ArgumentNullException(nameof(property));
|
||||
|
||||
var getterInfo = property.GetGetMethod(false);
|
||||
if (getterInfo != null)
|
||||
_getter = (Func<TClass, TProperty>)Delegate.CreateDelegate(typeof(Func<TClass, TProperty>), getterInfo);
|
||||
|
||||
var setterInfo = property.GetSetMethod(false);
|
||||
if (setterInfo != null)
|
||||
_setter = (Action<TClass, TProperty>)Delegate.CreateDelegate(typeof(Action<TClass, TProperty>), setterInfo);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
object IPropertyProxy.GetValue(object instance) =>
|
||||
_getter(instance as TClass);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IPropertyProxy.SetValue(object instance, object value) =>
|
||||
_setter(instance as TClass, (TProperty)value);
|
||||
}
|
||||
/// <param name="property">The property.</param>
|
||||
public PropertyProxy(PropertyInfo property) {
|
||||
if(property == null) {
|
||||
throw new ArgumentNullException(nameof(property));
|
||||
}
|
||||
|
||||
MethodInfo getterInfo = property.GetGetMethod(false);
|
||||
if(getterInfo != null) {
|
||||
this._getter = (Func<TClass, TProperty>)Delegate.CreateDelegate(typeof(Func<TClass, TProperty>), getterInfo);
|
||||
}
|
||||
|
||||
MethodInfo setterInfo = property.GetSetMethod(false);
|
||||
if(setterInfo != null) {
|
||||
this._setter = (Action<TClass, TProperty>)Delegate.CreateDelegate(typeof(Action<TClass, TProperty>), setterInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
Object IPropertyProxy.GetValue(Object instance) => this._getter(instance as TClass);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IPropertyProxy.SetValue(Object instance, Object value) => this._setter(instance as TClass, (TProperty)value);
|
||||
}
|
||||
}
|
||||
@@ -3,72 +3,54 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Swan.Reflection
|
||||
{
|
||||
namespace Swan.Reflection {
|
||||
/// <summary>
|
||||
/// A thread-safe cache of properties belonging to a given type.
|
||||
/// </summary>
|
||||
public class PropertyTypeCache : TypeCache<PropertyInfo> {
|
||||
/// <summary>
|
||||
/// A thread-safe cache of properties belonging to a given type.
|
||||
/// Gets the default cache.
|
||||
/// </summary>
|
||||
public class PropertyTypeCache : TypeCache<PropertyInfo>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the default cache.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default cache.
|
||||
/// </value>
|
||||
public static Lazy<PropertyTypeCache> DefaultCache { get; } = new Lazy<PropertyTypeCache>(() => new PropertyTypeCache());
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all properties.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to inspect.</typeparam>
|
||||
/// <param name="onlyPublic">if set to <c>true</c> [only public].</param>
|
||||
/// <returns>
|
||||
/// A collection with all the properties in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<PropertyInfo> RetrieveAllProperties<T>(bool onlyPublic = false)
|
||||
=> Retrieve<T>(onlyPublic ? GetAllPublicPropertiesFunc() : GetAllPropertiesFunc());
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all properties.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="onlyPublic">if set to <c>true</c> [only public].</param>
|
||||
/// <returns>
|
||||
/// A collection with all the properties in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<PropertyInfo> RetrieveAllProperties(Type type, bool onlyPublic = false)
|
||||
=> Retrieve(type, onlyPublic ? GetAllPublicPropertiesFunc() : GetAllPropertiesFunc());
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the filtered properties.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="onlyPublic">if set to <c>true</c> [only public].</param>
|
||||
/// <param name="filter">The filter.</param>
|
||||
/// <returns>
|
||||
/// A collection with all the properties in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<PropertyInfo> RetrieveFilteredProperties(
|
||||
Type type,
|
||||
bool onlyPublic,
|
||||
Func<PropertyInfo, bool> filter)
|
||||
=> Retrieve(type,
|
||||
onlyPublic ? GetAllPublicPropertiesFunc(filter) : GetAllPropertiesFunc(filter));
|
||||
|
||||
private static Func<Type, IEnumerable<PropertyInfo>> GetAllPropertiesFunc(
|
||||
Func<PropertyInfo, bool> filter = null)
|
||||
=> GetPropertiesFunc(
|
||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
|
||||
filter);
|
||||
|
||||
private static Func<Type, IEnumerable<PropertyInfo>> GetAllPublicPropertiesFunc(
|
||||
Func<PropertyInfo, bool> filter = null)
|
||||
=> GetPropertiesFunc(BindingFlags.Public | BindingFlags.Instance, filter);
|
||||
|
||||
private static Func<Type, IEnumerable<PropertyInfo>> GetPropertiesFunc(BindingFlags flags,
|
||||
Func<PropertyInfo, bool> filter = null)
|
||||
=> t => t.GetProperties(flags)
|
||||
.Where(filter ?? (p => p.CanRead || p.CanWrite));
|
||||
}
|
||||
/// <value>
|
||||
/// The default cache.
|
||||
/// </value>
|
||||
public static Lazy<PropertyTypeCache> DefaultCache { get; } = new Lazy<PropertyTypeCache>(() => new PropertyTypeCache());
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all properties.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to inspect.</typeparam>
|
||||
/// <param name="onlyPublic">if set to <c>true</c> [only public].</param>
|
||||
/// <returns>
|
||||
/// A collection with all the properties in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<PropertyInfo> RetrieveAllProperties<T>(Boolean onlyPublic = false) => this.Retrieve<T>(onlyPublic ? GetAllPublicPropertiesFunc() : GetAllPropertiesFunc());
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all properties.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="onlyPublic">if set to <c>true</c> [only public].</param>
|
||||
/// <returns>
|
||||
/// A collection with all the properties in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<PropertyInfo> RetrieveAllProperties(Type type, Boolean onlyPublic = false) => this.Retrieve(type, onlyPublic ? GetAllPublicPropertiesFunc() : GetAllPropertiesFunc());
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the filtered properties.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="onlyPublic">if set to <c>true</c> [only public].</param>
|
||||
/// <param name="filter">The filter.</param>
|
||||
/// <returns>
|
||||
/// A collection with all the properties in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<PropertyInfo> RetrieveFilteredProperties(Type type, Boolean onlyPublic, Func<PropertyInfo, Boolean> filter) => this.Retrieve(type, onlyPublic ? GetAllPublicPropertiesFunc(filter) : GetAllPropertiesFunc(filter));
|
||||
|
||||
private static Func<Type, IEnumerable<PropertyInfo>> GetAllPropertiesFunc(Func<PropertyInfo, Boolean> filter = null) => GetPropertiesFunc(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, filter);
|
||||
|
||||
private static Func<Type, IEnumerable<PropertyInfo>> GetAllPublicPropertiesFunc(Func<PropertyInfo, Boolean> filter = null) => GetPropertiesFunc(BindingFlags.Public | BindingFlags.Instance, filter);
|
||||
|
||||
private static Func<Type, IEnumerable<PropertyInfo>> GetPropertiesFunc(BindingFlags flags, Func<PropertyInfo, Boolean> filter = null) => t => t.GetProperties(flags).Where(filter ?? (p => p.CanRead || p.CanWrite));
|
||||
}
|
||||
}
|
||||
@@ -3,76 +3,69 @@ using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Swan.Collections;
|
||||
|
||||
namespace Swan.Reflection
|
||||
{
|
||||
namespace Swan.Reflection {
|
||||
/// <summary>
|
||||
/// A thread-safe cache of members belonging to a given type.
|
||||
///
|
||||
/// The Retrieve method is the most useful one in this class as it
|
||||
/// calls the retrieval process if the type is not contained
|
||||
/// in the cache.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of Member to be cached.</typeparam>
|
||||
public abstract class TypeCache<T> : CollectionCacheRepository<T> {
|
||||
/// <summary>
|
||||
/// A thread-safe cache of members belonging to a given type.
|
||||
///
|
||||
/// The Retrieve method is the most useful one in this class as it
|
||||
/// calls the retrieval process if the type is not contained
|
||||
/// in the cache.
|
||||
/// Determines whether the cache contains the specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of Member to be cached.</typeparam>
|
||||
public abstract class TypeCache<T> : CollectionCacheRepository<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether the cache contains the specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TOut">The type of the out.</typeparam>
|
||||
/// <returns>
|
||||
/// <c>true</c> if [contains]; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool Contains<TOut>() => ContainsKey(typeof(TOut));
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the properties stored for the specified type.
|
||||
/// If the properties are not available, it calls the factory method to retrieve them
|
||||
/// and returns them as an array of PropertyInfo.
|
||||
/// </summary>
|
||||
/// <typeparam name="TOut">The type of the out.</typeparam>
|
||||
/// <param name="factory">The factory.</param>
|
||||
/// <returns>An array of the properties stored for the specified type.</returns>
|
||||
public IEnumerable<T> Retrieve<TOut>(Func<Type, IEnumerable<T>> factory)
|
||||
=> Retrieve(typeof(TOut), factory);
|
||||
}
|
||||
|
||||
/// <typeparam name="TOut">The type of the out.</typeparam>
|
||||
/// <returns>
|
||||
/// <c>true</c> if [contains]; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public Boolean Contains<TOut>() => this.ContainsKey(typeof(TOut));
|
||||
|
||||
/// <summary>
|
||||
/// A thread-safe cache of fields belonging to a given type
|
||||
/// The Retrieve method is the most useful one in this class as it
|
||||
/// calls the retrieval process if the type is not contained
|
||||
/// in the cache.
|
||||
/// Retrieves the properties stored for the specified type.
|
||||
/// If the properties are not available, it calls the factory method to retrieve them
|
||||
/// and returns them as an array of PropertyInfo.
|
||||
/// </summary>
|
||||
public class FieldTypeCache : TypeCache<FieldInfo>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the default cache.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default cache.
|
||||
/// </value>
|
||||
public static Lazy<FieldTypeCache> DefaultCache { get; } = new Lazy<FieldTypeCache>(() => new FieldTypeCache());
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all fields.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to inspect.</typeparam>
|
||||
/// <returns>
|
||||
/// A collection with all the fields in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<FieldInfo> RetrieveAllFields<T>()
|
||||
=> Retrieve<T>(GetAllFieldsFunc());
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all fields.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>
|
||||
/// A collection with all the fields in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<FieldInfo> RetrieveAllFields(Type type)
|
||||
=> Retrieve(type, GetAllFieldsFunc());
|
||||
|
||||
private static Func<Type, IEnumerable<FieldInfo>> GetAllFieldsFunc()
|
||||
=> t => t.GetFields(BindingFlags.Public | BindingFlags.Instance);
|
||||
}
|
||||
/// <typeparam name="TOut">The type of the out.</typeparam>
|
||||
/// <param name="factory">The factory.</param>
|
||||
/// <returns>An array of the properties stored for the specified type.</returns>
|
||||
public IEnumerable<T> Retrieve<TOut>(Func<Type, IEnumerable<T>> factory) => this.Retrieve(typeof(TOut), factory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A thread-safe cache of fields belonging to a given type
|
||||
/// The Retrieve method is the most useful one in this class as it
|
||||
/// calls the retrieval process if the type is not contained
|
||||
/// in the cache.
|
||||
/// </summary>
|
||||
public class FieldTypeCache : TypeCache<FieldInfo> {
|
||||
/// <summary>
|
||||
/// Gets the default cache.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default cache.
|
||||
/// </value>
|
||||
public static Lazy<FieldTypeCache> DefaultCache { get; } = new Lazy<FieldTypeCache>(() => new FieldTypeCache());
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all fields.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to inspect.</typeparam>
|
||||
/// <returns>
|
||||
/// A collection with all the fields in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<FieldInfo> RetrieveAllFields<T>() => this.Retrieve<T>(GetAllFieldsFunc());
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all fields.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>
|
||||
/// A collection with all the fields in the given type.
|
||||
/// </returns>
|
||||
public IEnumerable<FieldInfo> RetrieveAllFields(Type type) => this.Retrieve(type, GetAllFieldsFunc());
|
||||
|
||||
private static Func<Type, IEnumerable<FieldInfo>> GetAllFieldsFunc() => t => t.GetFields(BindingFlags.Public | BindingFlags.Instance);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user