You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
3.0 KiB
74 lines
3.0 KiB
2 years ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Collections.ObjectModel;
|
||
|
using System.Linq;
|
||
|
using System.Reflection;
|
||
|
using System.Text;
|
||
|
|
||
|
namespace gaemstone.Utility;
|
||
|
|
||
|
public static class ReflectionExtensions
|
||
|
{
|
||
|
public static string GetFriendlyName(this Type type)
|
||
|
{
|
||
|
if (!type.IsGenericType) return type.Name;
|
||
|
var name = type.Name;
|
||
|
var sb = new StringBuilder(name[..name.IndexOf('`')]);
|
||
|
sb.Append('<');
|
||
|
sb.AppendJoin(",", type.GenericTypeArguments.Select(GetFriendlyName));
|
||
|
sb.Append('>');
|
||
|
return sb.ToString();
|
||
|
}
|
||
|
|
||
|
public static T? Get<T>(this MemberInfo member)
|
||
|
where T : Attribute => member.GetCustomAttribute<T>();
|
||
|
public static IEnumerable<T> GetMultiple<T>(this MemberInfo member)
|
||
|
where T : Attribute => member.GetCustomAttributes<T>();
|
||
|
public static bool Has<T>(this MemberInfo member)
|
||
|
where T : Attribute => member.GetCustomAttribute<T>() != null;
|
||
|
|
||
|
public static T? Get<T>(this ParameterInfo member)
|
||
|
where T : Attribute => member.GetCustomAttribute<T>();
|
||
|
public static IEnumerable<T> GetMultiple<T>(this ParameterInfo member)
|
||
|
where T : Attribute => member.GetCustomAttributes<T>();
|
||
|
public static bool Has<T>(this ParameterInfo member)
|
||
|
where T : Attribute => member.GetCustomAttribute<T>() != null;
|
||
|
|
||
|
|
||
|
public static bool IsNullable(this PropertyInfo property) =>
|
||
|
IsNullable(property.PropertyType, property.DeclaringType, property.CustomAttributes);
|
||
|
public static bool IsNullable(this FieldInfo field) =>
|
||
|
IsNullable(field.FieldType, field.DeclaringType, field.CustomAttributes);
|
||
|
public static bool IsNullable(this ParameterInfo parameter) =>
|
||
|
IsNullable(parameter.ParameterType, parameter.Member, parameter.CustomAttributes);
|
||
|
|
||
|
// https://stackoverflow.com/a/58454489
|
||
|
static bool IsNullable(Type memberType, MemberInfo? declaringType, IEnumerable<CustomAttributeData> customAttributes)
|
||
|
{
|
||
|
if (memberType.IsValueType) return (Nullable.GetUnderlyingType(memberType) != null);
|
||
|
|
||
|
var nullable = customAttributes.FirstOrDefault(
|
||
|
x => (x.AttributeType.FullName == "System.Runtime.CompilerServices.NullableAttribute"));
|
||
|
if ((nullable != null) && (nullable.ConstructorArguments.Count == 1)) {
|
||
|
var attributeArgument = nullable.ConstructorArguments[0];
|
||
|
if (attributeArgument.ArgumentType == typeof(byte[])) {
|
||
|
var args = (ReadOnlyCollection<CustomAttributeTypedArgument>)attributeArgument.Value!;
|
||
|
if ((args.Count > 0) && (args[0].ArgumentType == typeof(byte)))
|
||
|
return (byte)args[0].Value! == 2;
|
||
|
} else if (attributeArgument.ArgumentType == typeof(byte))
|
||
|
return (byte)attributeArgument.Value! == 2;
|
||
|
}
|
||
|
|
||
|
for (var type = declaringType; type != null; type = type.DeclaringType) {
|
||
|
var context = type.CustomAttributes.FirstOrDefault(
|
||
|
x => (x.AttributeType.FullName == "System.Runtime.CompilerServices.NullableContextAttribute"));
|
||
|
if ((context != null) && (context.ConstructorArguments.Count == 1) &&
|
||
|
(context.ConstructorArguments[0].ArgumentType == typeof(byte)))
|
||
|
return (byte)context.ConstructorArguments[0].Value! == 2;
|
||
|
}
|
||
|
|
||
|
// Couldn't find a suitable attribute.
|
||
|
return false;
|
||
|
}
|
||
|
}
|