public override DbgDotNetValueNode[] GetChildren(LanguageValueNodeFactory valueNodeFactory, DbgEvaluationInfo evalInfo, ulong index, int count, DbgValueNodeEvaluationOptions options, ReadOnlyCollection <string>?formatSpecifiers)
        {
            var res = count == 0 ? Array.Empty <DbgDotNetValueNode>() : new DbgDotNetValueNode[count];
            DbgDotNetValueResult newValue = default;

            try {
                var output      = ObjectCache.AllocDotNetTextOutput();
                var elementType = valueInfo.Value.Type.GetElementType() !;
                var castType    = NeedCast(slotType, valueInfo.Value.Type) ? valueInfo.Value.Type : null;
                for (int i = 0; i < res.Length; i++)
                {
                    evalInfo.CancellationToken.ThrowIfCancellationRequested();

                    string expression;
                    uint   arrayIndex = (uint)index + (uint)i;
                    newValue = valueInfo.Value.GetArrayElementAt(arrayIndex);

                    if (dimensionInfos.Length == 1)
                    {
                        int baseIndex = (int)arrayIndex + dimensionInfos[0].BaseIndex;
                        expression = valueNodeFactory.GetExpression(valueInfo.Expression, baseIndex, castType, addParens);
                        owner.FormatArrayName(output, baseIndex);
                    }
                    else
                    {
                        uint indexLeft = arrayIndex;
                        Debug2.Assert(indexes is not null);
                        for (int j = dimensionInfos.Length - 1; j >= 0; j--)
                        {
                            indexes[j] = (int)(indexLeft % dimensionInfos[j].Length) + dimensionInfos[j].BaseIndex;
                            indexLeft  = indexLeft / dimensionInfos[j].Length;
                        }
                        expression = valueNodeFactory.GetExpression(valueInfo.Expression, indexes, castType, addParens);
                        owner.FormatArrayName(output, indexes);
                    }

                    var name = output.CreateAndReset();
                    DbgDotNetValueNode?newNode;
                    if (newValue.HasError)
                    {
                        newNode = valueNodeFactory.CreateError(evalInfo, name, newValue.ErrorMessage !, expression, false);
                    }
                    else
                    {
                        newNode = null;
                        if (CSharpDynamicPropertyHelper.IsCSharpDynamicProperty(newValue.Value !.Type))
                        {
                            var info = CSharpDynamicPropertyHelper.GetRealValue(evalInfo, newValue.Value);
                            if (info.name is not null)
                            {
                                newValue.Value.Dispose();
                                name       = new DbgDotNetText(new DbgDotNetTextPart(DbgTextColor.DebugViewPropertyName, info.name));
                                expression = valueNodeFactory.GetFieldExpression(expression, info.valueField.Name, null, false);
                                newNode    = valueNodeFactory.Create(evalInfo, name, info.value, formatSpecifiers, options, expression, PredefinedDbgValueNodeImageNames.DynamicViewElement, true, false, info.valueField.FieldType, false);
                            }
                        }
                        if (newNode is null)
                        {
                            newNode = valueNodeFactory.Create(evalInfo, name, newValue.Value, formatSpecifiers, options, expression, PredefinedDbgValueNodeImageNames.ArrayElement, false, false, elementType, false);
                        }
                    }
                    newValue = default;
                    res[i]   = newNode;
                }
                ObjectCache.Free(ref output);
            }
            catch {
                evalInfo.Context.Process.DbgManager.Close(res.Where(a => a is not null));
                newValue.Value?.Dispose();
                throw;
            }
            return(res);
        }
        protected (DbgDotNetValueNode node, bool canHide) CreateValueNode(DbgEvaluationInfo evalInfo, bool addParens, DmdType slotType, DbgDotNetValue value, int index, DbgValueNodeEvaluationOptions options, string baseExpression, ReadOnlyCollection <string> formatSpecifiers)
        {
            var runtime = evalInfo.Runtime.GetDotNetRuntime();

            if ((evalOptions & DbgValueNodeEvaluationOptions.RawView) != 0)
            {
                options |= DbgValueNodeEvaluationOptions.RawView;
            }
            DbgDotNetValueResult valueResult = default;

            try {
                ref var info = ref membersCollection.Members[index];
                string  expression, imageName;
                bool    isReadOnly;
                DmdType expectedType;
                var     castType = info.NeedCast || NeedCast(slotType, GetMemberDeclaringType(info.Member)) ? info.Member.DeclaringType : null;
                switch (info.Member.MemberType)
                {
                case DmdMemberTypes.Field:
                    var field = (DmdFieldInfo)info.Member;
                    expression   = valueNodeFactory.GetFieldExpression(baseExpression, field.Name, castType, addParens);
                    expectedType = field.FieldType;
                    imageName    = ImageNameUtils.GetImageName(field);
                    valueResult  = runtime.LoadField(evalInfo, value, field);
                    // We should be able to change read only fields (we're a debugger), but since the
                    // compiler will complain, we have to prevent the user from editing the value.
                    isReadOnly = field.IsInitOnly;
                    break;

                case DmdMemberTypes.Property:
                    var property = (DmdPropertyInfo)info.Member;
                    expression   = valueNodeFactory.GetPropertyExpression(baseExpression, property.Name, castType, addParens);
                    expectedType = property.PropertyType;
                    imageName    = ImageNameUtils.GetImageName(property);
                    if ((options & DbgValueNodeEvaluationOptions.NoFuncEval) != 0)
                    {
                        isReadOnly  = true;
                        valueResult = DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.FuncEvalDisabled);
                    }
                    else
                    {
                        var getter = property.GetGetMethod(DmdGetAccessorOptions.All) ?? throw new InvalidOperationException();
                        valueResult = runtime.Call(evalInfo, value, getter, Array.Empty <object>(), DbgDotNetInvokeOptions.None);
                        isReadOnly  = (object)property.GetSetMethod(DmdGetAccessorOptions.All) == null;
                    }
                    break;

                default:
                    throw new InvalidOperationException();
                }

                DbgDotNetValueNode newNode;
                bool canHide    = true;
                var  customInfo = TryCreateInstanceValueNode(evalInfo, valueResult);
                if (customInfo.node != null)
                {
                    (newNode, canHide) = customInfo;
                }
                else if (valueResult.HasError)
                {
                    newNode = valueNodeFactory.CreateError(evalInfo, info.Name, valueResult.ErrorMessage, expression, false);
                    canHide = false;
                }
                else if (valueResult.ValueIsException)
                {
                    newNode = valueNodeFactory.Create(evalInfo, info.Name, valueResult.Value, formatSpecifiers, options, expression, PredefinedDbgValueNodeImageNames.Error, true, false, expectedType, false);
                }
                else
                {
                    newNode = valueNodeFactory.Create(evalInfo, info.Name, valueResult.Value, formatSpecifiers, options, expression, imageName, isReadOnly, false, expectedType, false);
                }

                valueResult = default;
                return(newNode, canHide);
            }