[英]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 <,,>及其后代關聯的可視化工具?
-
秘訣是創建自定義的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.