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.
73 lines
3.0 KiB
73 lines
3.0 KiB
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; |
|
} |
|
}
|
|
|