< Summary

Information
Class: System.Text.Json.Serialization.Metadata.ReflectionMemberAccessor
Assembly: System.Text.Json
File(s): C:\h\w\B31A098C\w\BB5A0A33\e\runtime-utils\Runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Serialization\Metadata\ReflectionMemberAccessor.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 121
Coverable lines: 121
Total lines: 175
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 29
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

C:\h\w\B31A098C\w\BB5A0A33\e\runtime-utils\Runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Serialization\Metadata\ReflectionMemberAccessor.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Collections.Generic;
 5using System.Diagnostics;
 6using System.Diagnostics.CodeAnalysis;
 7using System.Reflection;
 8
 9namespace System.Text.Json.Serialization.Metadata
 10{
 11    [RequiresDynamicCode(JsonSerializer.SerializationRequiresDynamicCodeMessage)]
 12    [RequiresUnreferencedCode(JsonSerializer.SerializationRequiresDynamicCodeMessage)]
 13    internal sealed class ReflectionMemberAccessor : MemberAccessor
 14    {
 015        public ReflectionMemberAccessor()
 016        {
 017        }
 18
 19        public override Func<object>? CreateParameterlessConstructor(Type type, ConstructorInfo? ctorInfo)
 020        {
 021            Debug.Assert(type != null);
 022            Debug.Assert(ctorInfo is null || ctorInfo.GetParameters().Length == 0);
 23
 024            if (type.IsAbstract)
 025            {
 026                return null;
 27            }
 28
 029            if (ctorInfo is null)
 030            {
 031                return type.IsValueType
 032                    ? () => Activator.CreateInstance(type, nonPublic: false)!
 033                    : null;
 34            }
 35
 036            return () => ctorInfo.Invoke(null);
 037        }
 38
 39        public override Func<object[], T> CreateParameterizedConstructor<T>(ConstructorInfo constructor)
 040        {
 041            Type type = typeof(T);
 42
 043            Debug.Assert(!type.IsAbstract);
 044            Debug.Assert(constructor.DeclaringType == type && constructor.IsPublic && !constructor.IsStatic);
 45
 046            int parameterCount = constructor.GetParameters().Length;
 47
 048            return (arguments) =>
 049            {
 050                // The input array was rented from the shared ArrayPool, so its size is likely to be larger than the par
 051                // The emit equivalent of this method does not (need to) allocate here + transfer the objects.
 052                object[] argsToPass = new object[parameterCount];
 053
 054                for (int i = 0; i < parameterCount; i++)
 055                {
 056                    argsToPass[i] = arguments[i];
 057                }
 058
 059                try
 060                {
 061                    return (T)constructor.Invoke(argsToPass);
 062                }
 063                catch (TargetInvocationException e)
 064                {
 065                    // Plumb ArgumentException through for tuples with more than 7 generic parameters, e.g.
 066                    // System.ArgumentException : The last element of an eight element tuple must be a Tuple.
 067                    // This doesn't apply to the method below as it supports a max of 4 constructor params.
 068                    throw e.InnerException ?? e;
 069                }
 070            };
 071        }
 72
 73        public override JsonTypeInfo.ParameterizedConstructorDelegate<T, TArg0, TArg1, TArg2, TArg3>?
 74            CreateParameterizedConstructor<T, TArg0, TArg1, TArg2, TArg3>(ConstructorInfo constructor)
 075        {
 076            Type type = typeof(T);
 77
 078            Debug.Assert(!type.IsAbstract);
 079            Debug.Assert(constructor.DeclaringType == type && constructor.IsPublic && !constructor.IsStatic);
 80
 081            int parameterCount = constructor.GetParameters().Length;
 82
 083            Debug.Assert(parameterCount <= JsonConstants.UnboxedParameterCountThreshold);
 84
 085            return (arg0, arg1, arg2, arg3) =>
 086            {
 087                object[] arguments = new object[parameterCount];
 088
 089                for (int i = 0; i < parameterCount; i++)
 090                {
 091                    switch (i)
 092                    {
 093                        case 0:
 094                            arguments[0] = arg0!;
 095                            break;
 096                        case 1:
 097                            arguments[1] = arg1!;
 098                            break;
 099                        case 2:
 0100                            arguments[2] = arg2!;
 0101                            break;
 0102                        case 3:
 0103                            arguments[3] = arg3!;
 0104                            break;
 0105                        default:
 0106                            Debug.Fail("We shouldn't be here if there are more than 4 parameters.");
 0107                            throw new InvalidOperationException();
 0108                    }
 0109                }
 0110
 0111                return (T)constructor.Invoke(arguments);
 0112            };
 0113        }
 114
 115        public override Action<TCollection, object?> CreateAddMethodDelegate<[DynamicallyAccessedMembers(DynamicallyAcce
 0116        {
 0117            Type collectionType = typeof(TCollection);
 0118            Type elementType = JsonTypeInfo.ObjectType;
 119
 120            // We verified this won't be null when we created the converter for the collection type.
 0121            MethodInfo addMethod = (collectionType.GetMethod("Push") ?? collectionType.GetMethod("Enqueue"))!;
 122
 0123            return delegate (TCollection collection, object? element)
 0124            {
 0125                addMethod.Invoke(collection, new object[] { element! });
 0126            };
 0127        }
 128
 129        public override Func<IEnumerable<TElement>, TCollection> CreateImmutableEnumerableCreateRangeDelegate<TCollectio
 0130        {
 0131            MethodInfo createRange = typeof(TCollection).GetImmutableEnumerableCreateRangeMethod(typeof(TElement));
 0132            return (Func<IEnumerable<TElement>, TCollection>)createRange.CreateDelegate(
 0133                typeof(Func<IEnumerable<TElement>, TCollection>));
 0134        }
 135
 136        public override Func<IEnumerable<KeyValuePair<TKey, TValue>>, TCollection> CreateImmutableDictionaryCreateRangeD
 0137        {
 0138            MethodInfo createRange = typeof(TCollection).GetImmutableDictionaryCreateRangeMethod(typeof(TKey), typeof(TV
 0139            return (Func<IEnumerable<KeyValuePair<TKey, TValue>>, TCollection>)createRange.CreateDelegate(
 0140                typeof(Func<IEnumerable<KeyValuePair<TKey, TValue>>, TCollection>));
 0141        }
 142
 143        public override Func<object, TProperty> CreatePropertyGetter<TProperty>(PropertyInfo propertyInfo)
 0144        {
 0145            MethodInfo getMethodInfo = propertyInfo.GetMethod!;
 146
 0147            return delegate (object obj)
 0148            {
 0149                return (TProperty)getMethodInfo.Invoke(obj, null)!;
 0150            };
 0151        }
 152
 153        public override Action<object, TProperty> CreatePropertySetter<TProperty>(PropertyInfo propertyInfo)
 0154        {
 0155            MethodInfo setMethodInfo = propertyInfo.SetMethod!;
 156
 0157            return delegate (object obj, TProperty value)
 0158            {
 0159                setMethodInfo.Invoke(obj, new object[] { value! });
 0160            };
 0161        }
 162
 163        public override Func<object, TProperty> CreateFieldGetter<TProperty>(FieldInfo fieldInfo) =>
 0164            delegate (object obj)
 0165            {
 0166                return (TProperty)fieldInfo.GetValue(obj)!;
 0167            };
 168
 169        public override Action<object, TProperty> CreateFieldSetter<TProperty>(FieldInfo fieldInfo) =>
 0170            delegate (object obj, TProperty value)
 0171            {
 0172                fieldInfo.SetValue(obj, value);
 0173            };
 174    }
 175}