Hi im trying to create a custom Visualizer for the DbCommand object that should be used in Visual studio 2013.
i have the following code
using VisualizerTest;
using Microsoft.VisualStudio.DebuggerVisualizers;
using System;
using System.Data.Common;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
[assembly: DebuggerVisualizer(typeof(TestVisualizer), typeof(CommandObjectSource), Target = typeof(DbCommand), Description = "Test")]
namespace VisualizerTest
{
public class TestVisualizer : DialogDebuggerVisualizer
{
protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
{
DbCommand command;
try
{
using (Stream stream = objectProvider.GetData())
{
BinaryFormatter formatter = new BinaryFormatter();
command = (DbCommand)formatter.Deserialize(stream);
}
MessageBox.Show(command.CommandText);
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
namespace VisualizerTest
{
[Serializable]
public class CommandObjectSource : VisualizerObjectSource
{
public override void GetData(object target, Stream outgoingData)
{
if (target != null && target is DbCommand)
{
DbCommand command = (DbCommand)target;
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(outgoingData, command);
}
}
}
}
But the CommandObjectSource is never invoked and instead i get a exception
Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.RemoteObjectSourceException: Type 'System.Data.SqlClient.SqlCommand' in Assembly 'System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.
My understanding was that by using a custom VisualizerObjectSource i would get around the Serialization issue?
As a side note i have tried to change Target = typeof(DbCommand) to Target = typeof(SqlCommand) and it made no difference.
Test code:
class Program
{
static void Main(string[] args)
{
using (SqlCommand command = new SqlCommand("SELECT Field1 FROM table WHERE Field2 = @Value1"))
{
command.Parameters.AddWithValue("@Value1", 1338);
TestValue(command);
}
Console.ReadKey();
}
static void TestValue(object value)
{
VisualizerDevelopmentHost visualizerHost = new VisualizerDevelopmentHost(value, typeof(TestVisualizer));
visualizerHost.ShowVisualizer();
}
}
Because you are explicitly creating the
VisualizerDevelopmentHostit won't use theDebuggerVisualizerAttributeso you have to pass in yourCommandObjectSourceas the third parameter:With this change your
CommandObjectSourcewill be called but you still have the serialization problem because theBinaryFormatteralso needs the class to be marked asSeralizabe...So you should probably only include the
CommandText(or create a new DTO object and seralize that if you need multiple properties) with:And read it with: