75 lines
3.2 KiB
C#
75 lines
3.2 KiB
C#
using System.Reflection;
|
|
|
|
namespace Syntriax.Engine.Serialization;
|
|
|
|
internal static class Utils
|
|
{
|
|
internal static bool HasAttribute<T>(this MemberInfo memberInfo) where T : Attribute => memberInfo.GetCustomAttribute<T>() is not null;
|
|
internal static bool IsEnumerable(this Type type) => typeof(System.Collections.IEnumerable).IsAssignableFrom(type) && type != typeof(string);
|
|
|
|
internal static TypeData GetTypeData(this Type objectType)
|
|
{
|
|
List<FieldInfo> fieldInfos = GetFieldInfosIncludingBaseClasses(objectType, BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public);
|
|
|
|
List<PropertyInfo> propertyInfos = GetPropertyInfosIncludingBaseClasses(objectType, BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public)
|
|
.Where(pi => pi.SetMethod is not null)
|
|
.ToList();
|
|
|
|
return new TypeData(fieldInfos, propertyInfos);
|
|
}
|
|
|
|
internal static List<FieldInfo> GetFieldInfosIncludingBaseClasses(Type type, BindingFlags bindingFlags)
|
|
{
|
|
if (type.BaseType is null)
|
|
return [.. type.GetFields(bindingFlags)];
|
|
|
|
Type currentType = type;
|
|
FieldInfoComparer fieldComparer = new();
|
|
HashSet<FieldInfo> fieldInfoList = new(type.GetFields(bindingFlags), fieldComparer);
|
|
|
|
while (currentType.BaseType is Type baseType)
|
|
{
|
|
currentType = baseType;
|
|
fieldInfoList.UnionWith(currentType!.GetFields(bindingFlags));
|
|
}
|
|
|
|
return [.. fieldInfoList.OrderBy(fi => fi.Name)];
|
|
}
|
|
|
|
internal static List<PropertyInfo> GetPropertyInfosIncludingBaseClasses(Type type, BindingFlags bindingFlags)
|
|
{
|
|
if (type.BaseType is null)
|
|
return [.. type.GetProperties(bindingFlags)];
|
|
|
|
Type currentType = type;
|
|
PropertyInfoComparer propertyComparer = new();
|
|
HashSet<PropertyInfo> propertyInfoList = new(type.GetProperties(bindingFlags), propertyComparer);
|
|
|
|
while (currentType.BaseType is Type baseType)
|
|
{
|
|
currentType = baseType;
|
|
propertyInfoList.UnionWith(currentType.GetProperties(bindingFlags));
|
|
}
|
|
|
|
return [.. propertyInfoList.OrderBy(pi => pi.Name)];
|
|
}
|
|
|
|
private class FieldInfoComparer : IEqualityComparer<FieldInfo>
|
|
{
|
|
public bool Equals(FieldInfo? x, FieldInfo? y) => x?.DeclaringType == y?.DeclaringType && x?.Name == y?.Name;
|
|
public int GetHashCode(FieldInfo obj) => obj.Name.GetHashCode() ^ obj.DeclaringType!.GetHashCode();
|
|
}
|
|
|
|
private class PropertyInfoComparer : IEqualityComparer<PropertyInfo>
|
|
{
|
|
public bool Equals(PropertyInfo? x, PropertyInfo? y) => x?.DeclaringType == y?.DeclaringType && x?.Name == y?.Name;
|
|
public int GetHashCode(PropertyInfo obj) => obj.Name.GetHashCode() ^ obj.DeclaringType!.GetHashCode();
|
|
}
|
|
}
|
|
|
|
internal record struct TypeData(IEnumerable<FieldInfo> Fields, IEnumerable<PropertyInfo> Properties)
|
|
{
|
|
public static implicit operator (IEnumerable<FieldInfo> fields, IEnumerable<PropertyInfo> properties)(TypeData value) => (value.Fields, value.Properties);
|
|
public static implicit operator TypeData((IEnumerable<FieldInfo> fields, IEnumerable<PropertyInfo> properties) value) => new(value.fields, value.properties);
|
|
}
|