<PackageReference Include="Namotion.Reflection" Version="3.4.2" />

ObjectExtensions

public static class ObjectExtensions
Object extensions.
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; namespace Namotion.Reflection { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public static class ObjectExtensions { public static bool DisableNullabilityValidation { get; set; } public static bool HasProperty([System.Runtime.CompilerServices.Nullable(2)] this object obj, string propertyName) { return ((obj != null) ? obj.GetType().GetRuntimeProperty(propertyName) : null) != (PropertyInfo)null; } [System.Runtime.CompilerServices.NullableContext(2)] public static T TryGetPropertyValue<T>(this object obj, [System.Runtime.CompilerServices.Nullable(1)] string propertyName, T defaultValue = default(T)) { PropertyInfo propertyInfo = (obj != null) ? obj.GetType().GetRuntimeProperty(propertyName) : null; if (!(propertyInfo == (PropertyInfo)null)) return (T)propertyInfo.GetValue(obj); return defaultValue; } public static bool HasValidNullability(this object obj, bool checkChildren = true) { return !obj.ValidateNullability(checkChildren).Any(); } [System.Runtime.CompilerServices.NullableContext(2)] public static void EnsureValidNullability(this object obj, bool checkChildren = true) { if (obj != null) ValidateNullability(obj, obj.GetType().ToContextualType(), checkChildren ? new HashSet<object>() : null, null, false); } public static IEnumerable<string> ValidateNullability(this object obj, bool checkChildren = true) { List<string> list = new List<string>(); ValidateNullability(obj, obj.GetType().ToContextualType(), checkChildren ? new HashSet<object>() : null, list, false); return list; } private static void ValidateNullability(object obj, ContextualType type, [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] HashSet<object> checkedObjects, [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] List<string> errors, bool stopFirstFail) { if (!DisableNullabilityValidation && (!stopFirstFail || errors == null || !errors.Any()) && (checkedObjects == null || checkedObjects.Add(obj))) { if (checkedObjects != null) { IDictionary dictionary = obj as IDictionary; if (dictionary != null) { foreach (object item in dictionary.Keys.Cast<object>().Concat(dictionary.Values.Cast<object>())) { ValidateNullability(item, type.GenericArguments[1], checkedObjects, errors, stopFirstFail); } return; } } if (checkedObjects != null) { IEnumerable enumerable = obj as IEnumerable; if (enumerable != null && !(obj is string)) { ContextualType contextualType = type.ElementType ?? type.GenericArguments[0]; foreach (object item2 in enumerable.Cast<object>()) { if (item2 == null) { if (contextualType.Nullability == Nullability.NotNullable) { if (errors == null) throw new InvalidOperationException("The object's nullability is invalid, item in enumerable."); errors.Add(contextualType.Type.Name); if (stopFirstFail) break; } } else ValidateNullability(item2, contextualType, checkedObjects, errors, stopFirstFail); } return; } } if (!type.TypeInfo.IsValueType) { ContextualPropertyInfo[] contextualProperties = type.Type.GetContextualProperties(); int num = 0; ContextualPropertyInfo contextualPropertyInfo; while (true) { if (num >= contextualProperties.Length) return; contextualPropertyInfo = contextualProperties[num]; if (!contextualPropertyInfo.PropertyType.IsValueType && contextualPropertyInfo.CanRead && !contextualPropertyInfo.IsAttributeDefined<CompilerGeneratedAttribute>(true)) { object value = contextualPropertyInfo.GetValue(obj); if (value == null) { if (contextualPropertyInfo.Nullability == Nullability.NotNullable) { if (errors == null) break; errors.Add(contextualPropertyInfo.Name); if (stopFirstFail) return; } } else if (checkedObjects != null) { ValidateNullability(value, contextualPropertyInfo.PropertyType, checkedObjects, errors, stopFirstFail); } } num++; } throw new InvalidOperationException("The object's nullability is invalid, property: " + contextualPropertyInfo.PropertyType.Type.FullName + "." + contextualPropertyInfo.Name); } } } } }