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

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;
}
}