簡體   English   中英

應用無組件依賴的調試器可視化器

[英]Apply a debugger visualizer without assembly dependencies

我正在嘗試創建適用於各種對象的調試可視化器,而無需使可視化器程序集成為依賴項。 我想將此可視化工具應用於各種類,包括私有嵌套類,內部類以及涉及許多復雜泛型的類(父類和嵌套類)。 這意味着我正在創建僅包含關鍵數據的代理對象。

我不希望我的主裝配依賴可視化器裝配,也不希望可視化裝配知道主裝配的內膽。

在主裝配中,我看起來像這樣:

namespace MainAsm
{
    public interface IVisualizable
    {
        DebugProxy DebugVisualizer { get; }
    }

    [Serializable]
    public class DebugProxy
    {
        // data required for visualization here

        public DebugProxy() { }
        public DebugProxy(IVisualizable source)
        {
            var orig = source.DebugVisualizer;
            // copy properties from orig
        }
    }
}

然后對於可視化器,我有如下代碼:

[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 to grab additional properties and open a window
        }
    }
}

我希望能夠將可視化程序應用於任何知道如何創建DebugProxy的類。 如果我展開一個對象並單擊其DebugVisualizer屬性,顯然可以得到一個可視化器,但是我希望該可視化與頂層對象相關聯。 所以,如果我有這樣的事情:

[System.Diagnostics.DebuggerVisualizer(???)]
public class MyClass<TThis, T2, T3> : IVisualizable
    where TThis : MyClass<TThis, T2, T3>, new()
    where T2 : SomeOtherClass2<T2, T3>, new()
    where T3 : SomeOtherClass3<T2, T3>, new()
{
    DebugProxy IVisualizable.DebugVisualizer { get { return CreateProxy(); } }
}

問題是,我需要代替???嗎? 使它與MyClass <,,>及其后代關聯的可視化工具?

-

  • 如果我放置[System.Diagnostics.DebuggerTypeProxy(typeof(DebugProxy))],則DebugProxy不會顯示帶有可視化圖標
  • at Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.ManagedShim.DelegateHost.CreateViewer 如果我放置[System.Diagnostics.DebuggerVisualizer(“ dbg.Visualizer”)]則會在Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.ManagedShim.DelegateHost.CreateViewer處收到
  • " even though the log shows the correct path under "Initial PrivatePath = " when it tries to resolve the assembly. 如果我放置[System.Diagnostics.DebuggerVisualizer(“ dbg.Visualizer,dbg”)] ,即使日志在“ Initial PrivatePath =”下顯示了正確的路徑,我也會得到“ ”嘗試解析程序集時。
  • " The call stack is a series of methods in DebuggerVisualizeres.DebugViewerShim namespace: "DelegatedHost.CreateViewer" -> "PrivateCallback.MaybeDeserializeAndthrowException" -> "DebugeeHost.CreateSourceInternal" -> "RemoteObjectSourceException" 如果我放置[System.Diagnostics.DebuggerVisualizer(“ dbg.Visualizer”,“ Microsoft.VisualStudio.DebuggerVisualizers.VisualizerObjectSource”)]則會得到“ ”調用堆棧是DebuggerVisualizeres.DebugViewerShim中的一系列方法。命名空間:“ DelegatedHost.CreateViewer”->“ PrivateCallback.MaybeDeserializeAndthrowException”->“ DebugeeHost.CreateSourceInternal”->“ RemoteObjectSourceException”

秘訣是創建自定義的VisualizerObjectSource並將其放入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);
        }
    }
}

然后將以下屬性放在實現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=???"]

哪里??? 是程序集的公鑰。

具有CustomObjectSource的程序集進入GAC非常重要,因為這確保了無論其基本路徑設置為什么,都可以將其加載到調試對象應用程序域中。 確保它具有強名稱,並在Visual Studio命令提示符下使用“ gacutil / f / i dbg.dll”進行安裝。

然后,當您嘗試可視化類時,它將把CustomObjectSource加載到您的應用程序域中,使用CreateReplacementObject方法將其轉換為可序列化的類型,然后對DebugProxy對象而不是原始類型執行序列化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM