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

NullableFlagsSource

using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading; namespace Namotion.Reflection { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] internal readonly struct NullableFlagsSource { [System.Runtime.CompilerServices.Nullable(0)] private readonly struct CacheKey : IEquatable<CacheKey> { public Type Type { get; set; } [System.Runtime.CompilerServices.Nullable(2)] [field: System.Runtime.CompilerServices.Nullable(2)] public Assembly Assembly { [System.Runtime.CompilerServices.NullableContext(2)] get; [System.Runtime.CompilerServices.NullableContext(2)] set; } public CacheKey(Type Type, [System.Runtime.CompilerServices.Nullable(2)] Assembly Assembly) { Type = Type; Assembly = Assembly; } [System.Runtime.CompilerServices.NullableContext(0)] public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("CacheKey"); stringBuilder.Append(" { "); if (PrintMembers(stringBuilder)) stringBuilder.Append(' '); stringBuilder.Append('}'); return stringBuilder.ToString(); } [System.Runtime.CompilerServices.NullableContext(0)] private bool PrintMembers(StringBuilder builder) { builder.Append("Type = "); builder.Append(Type); builder.Append(", Assembly = "); builder.Append(Assembly); return true; } public static bool operator !=(CacheKey left, CacheKey right) { return !(left == right); } public static bool operator ==(CacheKey left, CacheKey right) { return left.Equals(right); } public override int GetHashCode() { return EqualityComparer<Type>.Default.GetHashCode(Type) * -1521134295 + EqualityComparer<Assembly>.Default.GetHashCode(Assembly); } [System.Runtime.CompilerServices.NullableContext(0)] public override bool Equals(object obj) { if (obj is CacheKey) return Equals((CacheKey)obj); return false; } public bool Equals(CacheKey other) { if (EqualityComparer<Type>.Default.Equals(Type, other.Type)) return EqualityComparer<Assembly>.Default.Equals(Assembly, other.Assembly); return false; } public void Deconstruct(out Type Type, [System.Runtime.CompilerServices.Nullable(2)] out Assembly Assembly) { Type = this.Type; Assembly = this.Assembly; } } private static Dictionary<CacheKey, NullableFlagsSource> _nullableCache = new Dictionary<CacheKey, NullableFlagsSource>(); [System.Runtime.CompilerServices.Nullable(2)] public readonly byte[] NullableFlags; public static NullableFlagsSource Create(Type type, [System.Runtime.CompilerServices.Nullable(2)] Assembly assembly = null) { Dictionary<CacheKey, NullableFlagsSource> nullableCache = _nullableCache; CacheKey cacheKey = new CacheKey(type, assembly); if (!nullableCache.TryGetValue(cacheKey, out NullableFlagsSource value)) { value = new NullableFlagsSource(type, assembly); Interlocked.CompareExchange(ref _nullableCache, new Dictionary<CacheKey, NullableFlagsSource>(nullableCache) { [cacheKey] = value }, nullableCache); } return value; } public static NullableFlagsSource Create(MemberInfo member) { return new NullableFlagsSource(member); } private NullableFlagsSource(Type type, [System.Runtime.CompilerServices.Nullable(2)] Assembly assembly) { byte[] nullableFlags = GetNullableFlags(type); if (nullableFlags == null && (object)assembly != null) nullableFlags = GetNullableFlags(assembly); NullableFlags = nullableFlags; } private NullableFlagsSource(MemberInfo memberInfo) { NullableFlags = GetNullableFlags(memberInfo); } [return: System.Runtime.CompilerServices.Nullable(2)] private static byte[] GetNullableFlags<[System.Runtime.CompilerServices.Nullable(0)] T>(T provider) where T : ICustomAttributeProvider { object[] customAttributes = provider.GetCustomAttributes(false); foreach (object obj in customAttributes) { Type type = obj.GetType(); if (type.Name == "NullableContextAttribute" && type.Namespace == "System.Runtime.CompilerServices") return new byte[1] { (byte)type.GetRuntimeField("Flag").GetValue(obj) }; } return null; } } }