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
VisualizerDevelopmentHost
it won't use theDebuggerVisualizerAttribute
so you have to pass in yourCommandObjectSource
as the third parameter:With this change your
CommandObjectSource
will be called but you still have the serialization problem because theBinaryFormatter
also 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: