Home

DumpContainer Extension

I frequently find myself writing

var dc = new DumpContainer(); 
dc.Dump; 
//somewhere else
dc.Content=MyObject;

And it got me thinking that an extension would be super useful.
So here is my first attempt

public static class MyExtensions
{
    static Dictionary<int, DumpContainer> containers = new Dictionary<int, LINQPad.DumpContainer>();
    static object ctx;

    // Write custom extension methods here. They will be available to all queries.
    public static T DumpToContainer<T>(this T obj, int containerNum)
    {
        var exh = ExecutionContext.Capture().GetHashCode();
        lock (containers)
        {
            if (!exh.Equals(ctx))
            {
                ctx = exh;
                containers.Clear();
            }
            if (!containers.ContainsKey(containerNum))
                containers.Add(containerNum, new DumpContainer().Dump());
            containers[containerNum].Content = obj;
        }
        return obj;
    }
}

and then it is as simple as

myObject.DumpToContainer(1)

When a query is re executed the results window is cleared. Which means the previously rendered DumpContainer's disappear. The ExecutionContext is a hacky attempt to know when to "re Dump" the DumpContainers on subsequent executions.
The lock is just to make it thread safe.

Any suggestions for improvements are welcome for the benefit of all.
If the idea is worthy of inclusion in a future release then please do!

Comments

  • I like this, and I am going to it add it my own 'MyExtensions'. (I might have already done something like this, but I hadn't figured out your ExecutionContext 'hack')

    But, the first change I am going to make is to add

    containers[containerNum].Refresh(); 
    

    after you have updated the container content.

    The reason for that is because I have been caught before with code like

     var customer = Customers.First();
    
     var dc = new DumpContainer().Dump();
     dc.Content = customer;
     customer.Phone = "xxx";
     dc.Content = customer;
    

    And I expect the new phone number to be displayed.

    I realise that this means the extension method behaves differently from the standard code, so may not be to everyone's liking.

  • Good suggestion, I've been hit by that too. I suspect the DumpContainer checks for object equality under the hood and does not re render the display if true.

  • Just noticed that this only works in LinqPad 6 as ExecutionContext.Capture().GetHashCode(); returns a different value every time in LinqPad 5

  • Found a solution, which feels is much better than using the ExecutionContext. Just replace

    var exh = ExecutionContext.Capture().GetHashCode();
    

    with

    var exh = Util.CurrentQuery;
    

    Working here for me on LP5 and 6

  • Note that you can update a DumpContainer while forcing a refresh by calling the UpdateContent method.

  • A v2 implementation if anyone is interested.
    Some better functionality and refactoring for cleaner code.

    public static class MyExtensions
    {
        static Dictionary<int, ContextContainer> containers = new Dictionary<int, ContextContainer>();
    
        private static void DumpIfNewContext(ContextContainer container)
        {
            if(!Util.CurrentQuery.Equals(container.Context))
            {
                container.Dump();
                container.Context = Util.CurrentQuery;
            }
        }
    
        private static ContextContainer GetContainer(int containerNum, bool applyCtx)
        {
            lock (containers)
            {
                if (!containers.ContainsKey(containerNum))
                    containers.Add(containerNum, new ContextContainer());
                if(applyCtx)
                    containers[containerNum].Context = Util.CurrentQuery;
                return containers[containerNum];
            }
        }
    
        public static ContextContainer GetContainer(int containerNum)
        {
            return GetContainer(containerNum, true);
        }
    
        public static T DumpToContainer<T>(this T obj, int containerNum)
        {
            var ctr = GetContainer(containerNum, false);
            ctr.Content = obj;
            ctr.Refresh();
            DumpIfNewContext(ctr);
            return obj;
        }
    
    }
    
    public class ContextContainer : DumpContainer
    {
        internal Query Context { get; set; }
    }
    

    This allows the query code to grab a reference to a previously generated container if necessary. For example

    Util.HorizontalRun(true, MyExtensions.GetContainer(1), MyExtensions.GetContainer(2)).Dump();
    DateTime.Now.DumpToContainer(1);
    new Button("Click Me!").DumpToContainer(2);
    
Sign In or Register to comment.