// Copyright (c) Ben A Adams. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading; namespace DTLib.Demystifier.Internal; /// /// A helper class that contains utilities methods for dealing with reflection. /// public static class ReflectionHelper { private static PropertyInfo? transformerNamesLazyPropertyInfo; /// /// Returns true if the is a value tuple type. /// public static bool IsValueTuple(this Type type) { return type.Namespace == "System" && type.Name.Contains("ValueTuple`"); } /// /// Returns true if the given is of type TupleElementNameAttribute. /// /// /// To avoid compile-time dependency hell with System.ValueTuple, this method uses reflection and not checks statically /// that /// the given is TupleElementNameAttribute. /// public static bool IsTupleElementNameAttribute(this Attribute attribute) { var attributeType = attribute.GetType(); return attributeType.Namespace == "System.Runtime.CompilerServices" && attributeType.Name == "TupleElementNamesAttribute"; } /// /// Returns 'TransformNames' property value from a given . /// /// /// To avoid compile-time dependency hell with System.ValueTuple, this method uses reflection /// instead of casting the attribute to a specific type. /// public static IList? GetTransformerNames(this Attribute attribute) { Debug.Assert(attribute.IsTupleElementNameAttribute()); var propertyInfo = GetTransformNamesPropertyInfo(attribute.GetType())!; return propertyInfo.GetValue(attribute) as IList; } private static PropertyInfo GetTransformNamesPropertyInfo(Type attributeType) { #pragma warning disable 8634 return LazyInitializer.EnsureInitialized(ref transformerNamesLazyPropertyInfo, #pragma warning restore 8634 () => attributeType.GetProperty("TransformNames", BindingFlags.Instance | BindingFlags.Public)!)!; } }