coding styles nullable

This commit is contained in:
2019-12-08 19:54:52 +01:00
parent c78348324a
commit aa9fcd4a36
109 changed files with 12952 additions and 14462 deletions
+153 -180
View File
@@ -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));
}
}
}
+33 -42
View File
@@ -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();
}
}
+104 -98
View File
@@ -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)) {
}
}
}
+237 -257
View File
@@ -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);
}
}
+19 -19
View File
@@ -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);
}
}
+103 -110
View File
@@ -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);
}
}
}
+37 -40
View File
@@ -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);
}
}
+48 -66
View File
@@ -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));
}
}
+61 -68
View File
@@ -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);
}
}