Got at least one data fetching method working; turns out, we can't use a patched LogicStack to get the data
This commit is contained in:
188
Vendor/Swan.Lite-3.1.0/Reflection/AttributeCache.cs
vendored
Normal file
188
Vendor/Swan.Lite-3.1.0/Reflection/AttributeCache.cs
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.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>
|
||||
/// 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
50
Vendor/Swan.Lite-3.1.0/Reflection/ConstructorTypeCache.cs
vendored
Normal file
50
Vendor/Swan.Lite-3.1.0/Reflection/ConstructorTypeCache.cs
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Swan.Reflection
|
||||
{
|
||||
/// <summary>
|
||||
/// A thread-safe cache of constructors belonging to a given type.
|
||||
/// </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();
|
||||
}
|
||||
}
|
||||
267
Vendor/Swan.Lite-3.1.0/Reflection/ExtendedTypeInfo.cs
vendored
Normal file
267
Vendor/Swan.Lite-3.1.0/Reflection/ExtendedTypeInfo.cs
vendored
Normal file
@@ -0,0 +1,267 @@
|
||||
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
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
45
Vendor/Swan.Lite-3.1.0/Reflection/IPropertyProxy.cs
vendored
Normal file
45
Vendor/Swan.Lite-3.1.0/Reflection/IPropertyProxy.cs
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Swan.Reflection
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a generic interface to store getters and setters for high speed access to properties.
|
||||
/// </summary>
|
||||
public interface IPropertyProxy
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the property.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the property.
|
||||
/// </summary>
|
||||
Type PropertyType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the associated reflection property info.
|
||||
/// </summary>
|
||||
PropertyInfo Property { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type owning this property proxy.
|
||||
/// </summary>
|
||||
Type EnclosingType { get; }
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
117
Vendor/Swan.Lite-3.1.0/Reflection/MethodInfoCache.cs
vendored
Normal file
117
Vendor/Swan.Lite-3.1.0/Reflection/MethodInfoCache.cs
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Swan.Reflection
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Method Info Cache.
|
||||
/// </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);
|
||||
}
|
||||
}
|
||||
}
|
||||
79
Vendor/Swan.Lite-3.1.0/Reflection/PropertyInfoProxy.cs
vendored
Normal file
79
Vendor/Swan.Lite-3.1.0/Reflection/PropertyInfoProxy.cs
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Swan.Reflection
|
||||
{
|
||||
/// <summary>
|
||||
/// The concrete and hidden implementation of the <see cref="IPropertyProxy"/> implementation.
|
||||
/// </summary>
|
||||
/// <seealso cref="IPropertyProxy" />
|
||||
internal sealed class PropertyInfoProxy : IPropertyProxy
|
||||
{
|
||||
private readonly Func<object, object>? _getter;
|
||||
private readonly Action<object, object?>? _setter;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PropertyInfoProxy"/> class.
|
||||
/// </summary>
|
||||
/// <param name="declaringType">Type of the declaring.</param>
|
||||
/// <param name="propertyInfo">The property information.</param>
|
||||
public PropertyInfoProxy(Type declaringType, PropertyInfo propertyInfo)
|
||||
{
|
||||
Property = propertyInfo;
|
||||
EnclosingType = declaringType;
|
||||
_getter = CreateLambdaGetter(declaringType, propertyInfo);
|
||||
_setter = CreateLambdaSetter(declaringType, propertyInfo);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public PropertyInfo Property { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Type EnclosingType { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => Property.Name;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Type PropertyType => Property.PropertyType;
|
||||
|
||||
/// <inheritdoc />
|
||||
public object? GetValue(object instance) => _getter?.Invoke(instance);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetValue(object instance, object? value) => _setter?.Invoke(instance, value);
|
||||
|
||||
private static Func<object, object>? CreateLambdaGetter(Type instanceType, PropertyInfo propertyInfo)
|
||||
{
|
||||
if (!propertyInfo.CanRead)
|
||||
return null;
|
||||
|
||||
var instanceParameter = Expression.Parameter(typeof(object), "instance");
|
||||
var typedInstance = Expression.Convert(instanceParameter, instanceType);
|
||||
var property = Expression.Property(typedInstance, propertyInfo);
|
||||
var convert = Expression.Convert(property, typeof(object));
|
||||
var dynamicGetter = (Func<object, object>)Expression.Lambda(convert, instanceParameter).Compile();
|
||||
|
||||
return dynamicGetter;
|
||||
}
|
||||
|
||||
private static Action<object, object?>? CreateLambdaSetter(Type instanceType, PropertyInfo propertyInfo)
|
||||
{
|
||||
if (!propertyInfo.CanWrite)
|
||||
return null;
|
||||
|
||||
var instanceParameter = Expression.Parameter(typeof(object), "instance");
|
||||
var valueParameter = Expression.Parameter(typeof(object), "value");
|
||||
|
||||
var typedInstance = Expression.Convert(instanceParameter, instanceType);
|
||||
var property = Expression.Property(typedInstance, propertyInfo);
|
||||
var propertyValue = Expression.Convert(valueParameter, propertyInfo.PropertyType);
|
||||
|
||||
var body = Expression.Assign(property, propertyValue);
|
||||
var dynamicSetter = Expression.Lambda<Action<object, object?>>(body, instanceParameter, valueParameter).Compile();
|
||||
|
||||
return dynamicSetter;
|
||||
}
|
||||
}
|
||||
}
|
||||
74
Vendor/Swan.Lite-3.1.0/Reflection/PropertyTypeCache.cs
vendored
Normal file
74
Vendor/Swan.Lite-3.1.0/Reflection/PropertyTypeCache.cs
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Swan.Reflection
|
||||
{
|
||||
/// <summary>
|
||||
/// A thread-safe cache of properties belonging to a given type.
|
||||
/// </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));
|
||||
}
|
||||
}
|
||||
78
Vendor/Swan.Lite-3.1.0/Reflection/TypeCache.cs
vendored
Normal file
78
Vendor/Swan.Lite-3.1.0/Reflection/TypeCache.cs
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Swan.Collections;
|
||||
|
||||
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>
|
||||
/// 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);
|
||||
}
|
||||
|
||||
/// <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>()
|
||||
=> 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user