11namespace SolidUtilities . Extensions
22{
33 using System ;
4+ using System . Collections . Generic ;
5+ using System . Linq ;
46 using System . Reflection ;
7+ using UnityEngine ;
58
69 /// <summary>Different useful extensions for <see cref="System.Type"/>.</summary>
710 public static class TypeExtensions
@@ -30,5 +33,89 @@ public static FieldInfo GetFieldAtPath(this Type parentType, string path)
3033
3134 return field ;
3235 }
36+
37+ /// <summary>
38+ /// Collects all the serializable fields of a class: private ones with SerializeField attribute and public ones.
39+ /// </summary>
40+ /// <param name="type">Class type to collect the fields from.</param>
41+ /// <returns>Collection of the serializable fields of a class.</returns>
42+ /// <example><code>
43+ /// var fields = objectType.GetSerializedFields();
44+ /// foreach (var field in fields)
45+ /// {
46+ /// string fieldLabel = ObjectNames.NicifyVariableName(field.Name);
47+ /// object fieldValue = field.GetValue(serializedObject);
48+ /// object newValue = DrawField(fieldLabel, fieldValue);
49+ /// field.SetValue(serializedObject, newValue);
50+ /// }
51+ /// </code></example>
52+ public static IEnumerable < FieldInfo > GetSerializedFields ( this Type type )
53+ {
54+ const BindingFlags instanceFilter = BindingFlags . Instance | BindingFlags . Public | BindingFlags . NonPublic ;
55+ var instanceFields = type . GetFields ( instanceFilter ) ;
56+ return instanceFields . Where ( field => field . IsPublic || field . GetCustomAttribute < SerializeField > ( ) != null ) ;
57+ }
58+
59+ /// <summary>Checks whether the type is nullable.</summary>
60+ /// <param name="type">The type to check.</param>
61+ /// <returns>True if the type is nullable.</returns>
62+ public static bool IsNullable ( this Type type )
63+ {
64+ return ! type . IsValueType || Nullable . GetUnderlyingType ( type ) != null ;
65+ }
66+
67+ /// <summary>
68+ /// Checks whether the type is derivative of a generic class without specifying its type parameter.
69+ /// </summary>
70+ /// <param name="typeToCheck">The type to check.</param>
71+ /// <param name="generic">The generic class without type parameter.</param>
72+ /// <returns>True if the type is subclass of the generic class.</returns>
73+ /// <example><code>
74+ /// class Base<T> { }
75+ /// class IntDerivative : Base<int> { }
76+ /// class StringDerivative : Base<string> { }
77+ ///
78+ /// bool intIsSubclass = typeof(IntDerivative).IsSubclassOfRawGeneric(typeof(Base<>)); // true
79+ /// bool stringIsSubclass = typeof(StringDerivative).IsSubclassOfRawGeneric(typeof(Base<>)); // true
80+ /// </code></example>
81+ public static bool IsSubclassOfRawGeneric ( this Type typeToCheck , Type generic )
82+ {
83+ while ( typeToCheck != null && typeToCheck != typeof ( object ) )
84+ {
85+ Type cur = typeToCheck . IsGenericType ? typeToCheck . GetGenericTypeDefinition ( ) : typeToCheck ;
86+
87+ if ( generic == cur )
88+ return true ;
89+
90+ typeToCheck = typeToCheck . BaseType ;
91+ }
92+
93+ return false ;
94+ }
95+
96+ /// <summary>
97+ /// Checks whether the type inherits from the base type.
98+ /// </summary>
99+ /// <param name="typeToCheck">The type to check.</param>
100+ /// <param name="baseType">
101+ /// The base type to check inheritance from. It can be a generic type without the type parameter.
102+ /// </param>
103+ /// <returns>Whether <paramref name="typeToCheck"/>> inherits <paramref name="baseType"/>.</returns>
104+ /// <example><code>
105+ /// class Base<T> { }
106+ /// class IntDerivative : Base<int> { }
107+ ///
108+ /// bool isAssignableWithTypeParam = typeof(typeof(Base<int>).IsAssignableFrom(IntDerivative)); // true
109+ /// bool isAssignableWithoutTypeParam = typeof(typeof(Base<>)).IsAssignableFrom(IntDerivative); // false
110+ /// bool inherits = typeof(IntDerivative).Inherits(typeof(Base<>)); // true
111+ /// </code></example>
112+ public static bool InheritsFrom ( this Type typeToCheck , Type baseType )
113+ {
114+ bool subClassOfRawGeneric = false ;
115+ if ( baseType . IsGenericType )
116+ subClassOfRawGeneric = typeToCheck . IsSubclassOfRawGeneric ( baseType ) ;
117+
118+ return baseType . IsAssignableFrom ( typeToCheck ) || subClassOfRawGeneric ;
119+ }
33120 }
34121}
0 commit comments