public override bool IsApplicable(IObjectValueRole <TValue> valueRole, IMetadataTypeLite instanceType,
                                   IPresentationOptions options,
                                   IUserDataHolder dataHolder)
 {
     // Note that DebuggerDisplayObjectPresenter checks options.AllowTargetInvoke here
     return(myUnityOptions.ExtensionsEnabled && options.AllowDebuggerDisplayEvaluation &&
            TryCacheDebuggerDisplay(valueRole, instanceType.GetGenericTypeDefinition(), dataHolder));
 }
        // Return null to allow other providers a chance. If we throw EvaluatorException, it will be presented to the
        // user. OperationCancelledException will be logged and we move on to the next presenter. Any other exception
        // will leak
        public override IValuePresentation PresentValue(IObjectValueRole <TValue> valueRole,
                                                        IMetadataTypeLite instanceType,
                                                        IPresentationOptions options,
                                                        IUserDataHolder dataHolder,
                                                        CancellationToken token)
        {
            var debuggerDisplayString = dataHolder.GetData(ourDebuggerDisplayStringKey);

            try
            {
                var valueReference    = valueRole.ValueReference;
                var thisObj           = valueReference.GetValue(options);
                var evaluationOptions =
                    valueReference.OriginatingFrame.DebuggerSession.Options.EvaluationOptions.Apply(options);

                // This can throw if there are members missing, which is entirely possible when debugging on a device,
                // due to stripping. It will throw EvaluatorException. Anything else is logged and thrown as a new
                // EvaluatorException. We can also get InvalidOperationException, but only if no other evaluators can
                // handle the current context, which is unlikely
                var displayString =
                    ExpressionEvaluators.EvaluateDisplayString(valueReference.OriginatingFrame, thisObj,
                                                               debuggerDisplayString, evaluationOptions, token);
                return(SimplePresentation.CreateSuccess(
                           ValuePresentationPart.Default(DisplayStringUtil.EscapeString(displayString)),
                           valueReference.DefaultFlags, instanceType, displayString));
            }
            catch (Exception ex)
            {
                // Log as warning, not error - there's nothing the user can do, and we're likely to encounter this with
                // device builds
                myLogger.Warn(ex,
                              comment: $"Unable to evaluate debugger display string for type ${instanceType.GetGenericTypeDefinition().FullName}: ${debuggerDisplayString}. " +
                              "Expected behaviour on devices due to stripping");
                return(null);
            }
        }