<PackageReference Include="System.Text.Json" Version="7.0.2" />

FSharpCoreReflectionProxy

using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace System.Text.Json.Serialization.Metadata { internal sealed class FSharpCoreReflectionProxy { public enum FSharpKind { Unrecognized, Option, ValueOption, List, Set, Map, Record, Union } public delegate TResult StructGetter<TStruct, TResult> (ref TStruct this) where TStruct : struct; private enum SourceConstructFlags { None = 0, SumType = 1, RecordType = 2, ObjectType = 3, Field = 4, Exception = 5, Closure = 6, Module = 7, UnionCase = 8, Value = 9, KindMask = 31, NonPublicRepresentation = 32 } public const string FSharpCoreUnreferencedCodeMessage = "Uses Reflection to access FSharp.Core components at runtime."; private static FSharpCoreReflectionProxy s_singletonInstance; private const string CompilationMappingAttributeTypeName = "Microsoft.FSharp.Core.CompilationMappingAttribute"; private readonly Type _compilationMappingAttributeType; private readonly MethodInfo _sourceConstructFlagsGetter; private readonly Type _fsharpOptionType; private readonly Type _fsharpValueOptionType; private readonly Type _fsharpListType; private readonly Type _fsharpSetType; private readonly Type _fsharpMapType; private readonly MethodInfo _fsharpListCtor; private readonly MethodInfo _fsharpSetCtor; private readonly MethodInfo _fsharpMapCtor; public static FSharpCoreReflectionProxy Instance => s_singletonInstance; [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Uses Reflection to access FSharp.Core components at runtime.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Uses Reflection to access FSharp.Core components at runtime.")] public static bool IsFSharpType(Type type) { if (s_singletonInstance == null) { Assembly fSharpCoreAssembly = GetFSharpCoreAssembly(type); if ((object)fSharpCoreAssembly != null) { if (s_singletonInstance == null) s_singletonInstance = new FSharpCoreReflectionProxy(fSharpCoreAssembly); return true; } return false; } return s_singletonInstance.GetFSharpCompilationMappingAttribute(type) != null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Uses Reflection to access FSharp.Core components at runtime.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Uses Reflection to access FSharp.Core components at runtime.")] private FSharpCoreReflectionProxy(Assembly fsharpCoreAssembly) { Type type = fsharpCoreAssembly.GetType("Microsoft.FSharp.Core.CompilationMappingAttribute"); _sourceConstructFlagsGetter = type.GetMethod("get_SourceConstructFlags", BindingFlags.Instance | BindingFlags.Public); _compilationMappingAttributeType = type; _fsharpOptionType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Core.FSharpOption`1"); _fsharpValueOptionType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Core.FSharpValueOption`1"); _fsharpListType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.FSharpList`1"); _fsharpSetType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.FSharpSet`1"); _fsharpMapType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.FSharpMap`2"); _fsharpListCtor = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.ListModule")?.GetMethod("OfSeq", BindingFlags.Static | BindingFlags.Public); _fsharpSetCtor = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.SetModule")?.GetMethod("OfSeq", BindingFlags.Static | BindingFlags.Public); _fsharpMapCtor = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.MapModule")?.GetMethod("OfSeq", BindingFlags.Static | BindingFlags.Public); } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Uses Reflection to access FSharp.Core components at runtime.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Uses Reflection to access FSharp.Core components at runtime.")] public FSharpKind DetectFSharpKind(Type type) { Attribute fSharpCompilationMappingAttribute = GetFSharpCompilationMappingAttribute(type); if (fSharpCompilationMappingAttribute != null) { if (type.IsGenericType) { Type genericTypeDefinition = type.GetGenericTypeDefinition(); if (genericTypeDefinition == _fsharpOptionType) return FSharpKind.Option; if (genericTypeDefinition == _fsharpValueOptionType) return FSharpKind.ValueOption; if (genericTypeDefinition == _fsharpListType) return FSharpKind.List; if (genericTypeDefinition == _fsharpSetType) return FSharpKind.Set; if (genericTypeDefinition == _fsharpMapType) return FSharpKind.Map; } switch (GetSourceConstructFlags(fSharpCompilationMappingAttribute) & SourceConstructFlags.KindMask) { case SourceConstructFlags.RecordType: return FSharpKind.Record; case SourceConstructFlags.SumType: return FSharpKind.Union; default: return FSharpKind.Unrecognized; } } return FSharpKind.Unrecognized; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Uses Reflection to access FSharp.Core components at runtime.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Uses Reflection to access FSharp.Core components at runtime.")] public Func<TFSharpOption, T> CreateFSharpOptionValueGetter<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)] TFSharpOption, T>() { MethodInfo methodInfo = EnsureMemberExists(typeof(TFSharpOption).GetMethod("get_Value", BindingFlags.Instance | BindingFlags.Public), "Microsoft.FSharp.Core.FSharpOption<T>.get_Value()"); return CreateDelegate<Func<TFSharpOption, T>>(methodInfo); } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Uses Reflection to access FSharp.Core components at runtime.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Uses Reflection to access FSharp.Core components at runtime.")] public Func<TElement, TFSharpOption> CreateFSharpOptionSomeConstructor<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)] TFSharpOption, TElement>() { MethodInfo methodInfo = EnsureMemberExists(typeof(TFSharpOption).GetMethod("Some", BindingFlags.Static | BindingFlags.Public), "Microsoft.FSharp.Core.FSharpOption<T>.Some(T value)"); return CreateDelegate<Func<TElement, TFSharpOption>>(methodInfo); } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Uses Reflection to access FSharp.Core components at runtime.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Uses Reflection to access FSharp.Core components at runtime.")] public StructGetter<TFSharpValueOption, TElement> CreateFSharpValueOptionValueGetter<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)] TFSharpValueOption, TElement>() where TFSharpValueOption : struct { MethodInfo methodInfo = EnsureMemberExists(typeof(TFSharpValueOption).GetMethod("get_Value", BindingFlags.Instance | BindingFlags.Public), "Microsoft.FSharp.Core.FSharpValueOption<T>.get_Value()"); return CreateDelegate<StructGetter<TFSharpValueOption, TElement>>(methodInfo); } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Uses Reflection to access FSharp.Core components at runtime.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Uses Reflection to access FSharp.Core components at runtime.")] public Func<TElement, TFSharpOption> CreateFSharpValueOptionSomeConstructor<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)] TFSharpOption, TElement>() { MethodInfo methodInfo = EnsureMemberExists(typeof(TFSharpOption).GetMethod("Some", BindingFlags.Static | BindingFlags.Public), "Microsoft.FSharp.Core.FSharpValueOption<T>.ValueSome(T value)"); return CreateDelegate<Func<TElement, TFSharpOption>>(methodInfo); } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Uses Reflection to access FSharp.Core components at runtime.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Uses Reflection to access FSharp.Core components at runtime.")] public Func<IEnumerable<TElement>, TFSharpList> CreateFSharpListConstructor<TFSharpList, TElement>() { return CreateDelegate<Func<IEnumerable<TElement>, TFSharpList>>(EnsureMemberExists(_fsharpListCtor, "Microsoft.FSharp.Collections.ListModule.OfSeq<T>(IEnumerable<T> source)").MakeGenericMethod(typeof(TElement))); } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Uses Reflection to access FSharp.Core components at runtime.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Uses Reflection to access FSharp.Core components at runtime.")] public Func<IEnumerable<TElement>, TFSharpSet> CreateFSharpSetConstructor<TFSharpSet, TElement>() { return CreateDelegate<Func<IEnumerable<TElement>, TFSharpSet>>(EnsureMemberExists(_fsharpSetCtor, "Microsoft.FSharp.Collections.SetModule.OfSeq<T>(IEnumerable<T> source)").MakeGenericMethod(typeof(TElement))); } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Uses Reflection to access FSharp.Core components at runtime.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Uses Reflection to access FSharp.Core components at runtime.")] public Func<IEnumerable<Tuple<TKey, TValue>>, TFSharpMap> CreateFSharpMapConstructor<TFSharpMap, TKey, TValue>() { return CreateDelegate<Func<IEnumerable<Tuple<TKey, TValue>>, TFSharpMap>>(EnsureMemberExists(_fsharpMapCtor, "Microsoft.FSharp.Collections.MapModule.OfSeq<TKey, TValue>(IEnumerable<Tuple<TKey, TValue>> source)").MakeGenericMethod(typeof(TKey), typeof(TValue))); } private Attribute GetFSharpCompilationMappingAttribute(Type type) { return type.GetCustomAttribute(_compilationMappingAttributeType, true); } private SourceConstructFlags GetSourceConstructFlags(Attribute compilationMappingAttribute) { if ((object)_sourceConstructFlagsGetter != null) return (SourceConstructFlags)_sourceConstructFlagsGetter.Invoke(compilationMappingAttribute, null); return SourceConstructFlags.None; } private static Assembly GetFSharpCoreAssembly(Type type) { object[] customAttributes = type.GetCustomAttributes(true); for (int i = 0; i < customAttributes.Length; i++) { Attribute attribute = (Attribute)customAttributes[i]; Type type2 = attribute.GetType(); if (type2.FullName == "Microsoft.FSharp.Core.CompilationMappingAttribute") return type2.Assembly; } return null; } private static TDelegate CreateDelegate<TDelegate>(MethodInfo methodInfo) where TDelegate : Delegate { return (TDelegate)Delegate.CreateDelegate(typeof(TDelegate), methodInfo, true); } private static TMemberInfo EnsureMemberExists<TMemberInfo>(TMemberInfo memberInfo, string memberName) where TMemberInfo : MemberInfo { if (memberInfo == null) ThrowHelper.ThrowMissingMemberException_MissingFSharpCoreMember(memberName); return memberInfo; } } }