Custom renderer for DbCommand

Hi I am trying to create a custom Visualizer for a DbCommand object to be used on 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 CommandObjectSource

never gets called and instead I get an 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 with a custom VisualizerObjectSource, would I get around the serialization issue?

As a side note, I tried changing Target = typeof(DbCommand)

to Target = typeof(SqlCommand)

and it didn't make any 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();
    }
}

      

+3


source to share


1 answer


Since you are explicitly creating it VisualizerDevelopmentHost

, it won't use DebuggerVisualizerAttribute

, so you need to pass yours CommandObjectSource

as the third parameter:

VisualizerDevelopmentHost visualizerHost = 
    new VisualizerDevelopmentHost(value, typeof(TestVisualizer),                  
                                         typeof(CommandObjectSource));

      

With this change will be called CommandObjectSource

, but you still have a serialization problem because it BinaryFormatter

also needs a class to be marked as Seralizabe

...

So you should probably only include CommandText

(or create a new DTO object and seralize that if you need multiple properties):



[Serializable]
public class CommandObjectSource : VisualizerObjectSource
{
    public override void GetData(object target, Stream outgoingData)
    {
        if (target != null && target is DbCommand)
        {
            DbCommand command = (DbCommand)target;

            var writer = new StreamWriter(outgoingData);
            writer.WriteLine(command.CommandText);
            writer.Flush();
        }
    }
}

      

And read it with:

public class TestVisualizer : DialogDebuggerVisualizer
{
    protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
    {
        string command;
        try
        {
            command = new StreamReader(objectProvider.GetData()).ReadLine();
            MessageBox.Show(command);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }
}

      

+4


source







All Articles