3

Depending on what is asked on this question Can the DebuggerDisplay attribute be applied to types one doesn't own, can one apply the DebuggerDisplay attribute to types from external assemblies?

If so, is there a way apply it specifically to a Microsoft.Office.Interop.Word.Range?


I tried the following code and it did not work:

<Assembly: DebuggerDisplay("text: {Text}", Target:=GetType(Word.Range))>

At a runtime Debuger displlays this string:

{System.__ComObject}

But 'System.__ComObject' is not accessible because it is 'Friend'.

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
codeDom
  • 1,623
  • 18
  • 54
  • The debugger probably can't use the transparent proxy used for COM objects in the same way that runtime code can. Try a `DebuggerTypeProxy` instead (even if it's a bit more work) – Jeroen Mostert Jan 23 '18 at 11:19
  • @JeroenMostert Can you give an example for DebuggerTypeProxy ? – codeDom Jan 23 '18 at 11:25
  • [Sure](https://learn.microsoft.com/visualstudio/debugger/using-the-debuggerdisplay-attribute). (Despite the title, it covers `DebuggerTypeProxy` as well.) – Jeroen Mostert Jan 23 '18 at 11:30

1 Answers1

7

But 'System.__ComObject' is not accessible because it is 'Friend'.

That's true. However System.__ComObject inherits from public MarshalByRefObject. And DebuggerDisplay attribute will work for all derived classes if you set it for their base class. So you could set typeof(MarshalByRefObject) as a target for DebuggerDisplay attribute.

If you do this, you can't just use {Text} in formatter because MarshalByRefObject does not have such property. To overcome this, you could define the simple static helper that will check what is the type of passed object. If it's a Range it will call Text on it. Otherwise it will default to obj.ToString():

public static class DisplayHelper
{
    public static string DisplayRange(MarshalByRefObject obj)
    {
        var range = obj as Range;
        return range?.Text ?? obj?.ToString() ?? "The value is null";
    }
}

Now you could set DebuggerDisplay attribute:

[assembly: DebuggerDisplay("text: {FullNamespace.Here.DisplayHelper.DisplayRange(this)}"
           , Target = typeof(MarshalByRefObject))]

Be sure to specify full namespace for DisplayHelper class (replace FullNamespace.Goes.Here with your actual namespace).

Here is result view in the debugger:

enter image description here

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
CodeFuller
  • 30,317
  • 3
  • 63
  • 79
  • Can I apply it somehow to all object types in my class, let's say in one specific namespace? This one works, but can I avoid duplicating it for all types? My extension accepts object [assembly: DebuggerDisplay("{WebApi.Models.DebuggerExtension.ToDebuggerString(this)}", Target = typeof(WebApi.Models.User))] – VladL Aug 17 '22 at 14:24