c# - Apply a debugger visualizer without assembly dependencies -
i trying create debug visualizer applies variety of objects without make visualizer assembly dependency. want apply visualizer variety of classes, including private nested, internal, , lots of complex generics involved (both of parent , nested classes). means i'm creating proxy object critical data involved.
i don't want main assembly have dependency on visualizer assembly, , don't want visualizer assembly know guts of main assembly.
in main assembly, have looks this:
namespace mainasm { public interface ivisualizable { debugproxy debugvisualizer { get; } } [serializable] public class debugproxy { // data required visualization here public debugproxy() { } public debugproxy(ivisualizable source) { var orig = source.debugvisualizer; // copy properties orig } } }
then visualizer, have code looks this:
[assembly:system.diagnostics.debuggervisualizer( typeof(dbg.visualizer), typeof(microsoft.visualstudio.debuggervisualizers.visualizerobjectsource), targettypename="mainasm.debugproxy, mainasm", description="mainasm debug visualizer")] namespace dbg { public class visualizer : microsoft.visualstudio.debuggervisualizers.dialogdebuggervisualizer { protected override void show( microsoft.visualstudio.debuggervisualizers.idialogvisualizerservice windowservice, microsoft.visualstudio.debuggervisualizers.ivisualizerobjectprovider objectprovider) { object data = objectprovider.getobject(); if (data == null) return; var t = data.gettype(); var prop = t.getproperty("debugvisualizer"); if (prop != null) { data = prop.getvalue(data, null) ?? data; } // use reflection grab additional properties , open window } } }
i want able apply visualizer class knows how create debugproxy. can visualizer if expand object , click on debugvisualizer property, want visualization associated top level object. if have this:
[system.diagnostics.debuggervisualizer(???)] public class myclass<tthis, t2, t3> : ivisualizable tthis : myclass<tthis, t2, t3>, new() t2 : someotherclass2<t2, t3>, new() t3 : someotherclass3<t2, t3>, new() { debugproxy ivisualizable.debugvisualizer { { return createproxy(); } } }
the question is, need put in place of ??? associate visualizer myclass<,,> , descendants?
--
- if put [system.diagnostics.debuggertypeproxy(typeof(debugproxy))] debugproxy doesn't show visualizer icon
- if put [system.diagnostics.debuggervisualizer("dbg.visualizer")], nullreferenceexception @ microsoft.visualstudio.debuggervisualizers.debugviewershim.managedshim.delegatehost.createviewer
- if put [system.diagnostics.debuggervisualizer("dbg.visualizer, dbg")], "could not load file or assembly dbg or 1 of dependencies" though log shows correct path under "initial privatepath = " when tries resolve assembly.
- if put [system.diagnostics.debuggervisualizer("dbg.visualizer", "microsoft.visualstudio.debuggervisualizers.visualizerobjectsource")], "cannot create visualizer object source." call stack series of methods in debuggervisualizeres.debugviewershim namespace: "delegatedhost.createviewer" -> "privatecallback.maybedeserializeandthrowexception" -> "debugeehost.createsourceinternal" -> "remoteobjectsourceexception"
the secret create customized visualizerobjectsource , put gac:
namespace dbg { public class customobjectsource : microsoft.visualstudio.debuggervisualizers.visualizerobjectsource { private static object convertobject(object oldobj) { if (oldobj == null) return null; foreach (var intf in oldobj.gettype().getinterfaces()) { var prop = intf.getproperty("debugvisualizer"); if (prop != null) return prop.getvalue(oldobj, null); } return oldobj; } public override void transferdata(object target, stream incomingdata, stream outgoingdata) { base.transferdata(convertobject(target), incomingdata, outgoingdata); } public override object createreplacementobject(object target, stream incomingdata) { return convertobject(base.createreplacementobject(convertobject(target), incomingdata)); } public override void getdata(object target, stream outgoingdata) { base.getdata(convertobject(target), outgoingdata); } } }
then put following attribute on classes implement ivisualizable:
[system.diagnostics.debuggervisualizer( "dbg.visualizer, dbg, version=1.0.0.0, culture=neutral, publickeytoken=???", "dbg.customobjectsource, dbg, version=1.0.0.0, culture=neutral, publickeytoken=???"]
where ??? public key of assembly.
it's important assembly customobjectsource goes gac, because ensures can loaded debugee app domain no matter base path set as. make sure has strong name , use "gacutil /f /i dbg.dll" visual studio command prompt install it.
then when try visualize class, load customobjectsource app domain, use createreplacementobject method convert serializable type, , perform serialization on debugproxy object instead of original type.
Comments
Post a Comment