Home
Options

Changing dumped property names

Hi,

Does anyone know if there's an in the box method of changing dumped property names to include using things like the period character?

My use case is that I often create info type classes on a per query basis and might throw in properties from other different classes.

In this situation I'd like to add a period in the property name when it's dumped.

For example, if you want to dump SectionInfo with 'SectionCount' split with a period:

public class SectionInfo
{
    public int SectionCount { get; set; }
}

new SectionInfo(){SectionCount = 2}.Dump();

Then the output might look like this:

I tried the DisplayName attribute but ideally I'd pass some mapping options to Dump particularly if you don't own the original class.

Maybe something like:

new SectionInfo(){SectionCount = 2}.Dump(MemberNameMap({"SectionCount", "Section.Count"}));

I'm still using LINQPad 5 and 7 together so ideally it would appear in both :)

Best regards

John

Comments

  • Options

    It's a hack, but you could do something like the following

    public static class Extensions
    {
        public static object RenameColumns<T>(this T input, params string[] names)
        {
            var hw = Util.CreateXhtmlWriter();
            hw.WriteLine(input);
            var html = hw?.ToString();
            for (int i = 0; i < names.Length; i += 2)
            {
                html = html?.Replace(">" + names[i] + "</th>", ">" + names[i + 1] + "</th>");
            }
            return Util.RawHtml(html);
        }
    }
    
    void Main()
    {   
        var si = new SectionInfo() { SectionCount = 2 , Name = "SectionCount" };
    
        si.RenameColumns("SectionCount", "Section.Count").Dump();
    
        List<SectionInfo> sections = new List<UserQuery.SectionInfo>();
        sections.Add(si);
        sections.Add(si);
    
        sections.RenameColumns("SectionCount", "Section.Count").Dump();
    }
    
    public class SectionInfo  
    {
        public int SectionCount { get; set; } 
        public string? Name  { get; set; } 
    }
    
    

    As you can see from the results below, it works with single objects and lists etc and only changes the header/column names.

    Works with LinqPad 5 and 7.

    I've done something similar where I wanted to insert spaces and a <br /> tag in some column names to make a report look better.

  • Options

    You could use an expando. Here are a couple of examples:

    var expando = (IDictionary<string, object>) new System.Dynamic.ExpandoObject();
    expando ["Section.Count"] = 123;
    expando.Dump();
    
    var uri = new Uri ("http://foo");
    var expando = (IDictionary<string, object>) Util.ToExpando (uri, exclude: "IsFile");
    expando ["Is File"] = uri.IsFile;
    expando.Dump();
    
  • Options

    Perfect. Thanks very much to you both.

    I've borrowed from both of your approaches:

    void Main()
    {
        var si = new SectionInfo() { NameAtHome = "John", SectionCount = 2 };
    
        si.DumpMapped(new Dictionary<string, string>(){
            {"SectionCount", "Section.Count" },
            {"NameAtHome", "Name@Home" }
        });
    
    }
    
    public class SectionInfo
    {
        public string NameAtHome { get; set; }
        public int SectionCount { get; set; }
    }
    
    public static class NameExtensions
    {
        public static void DumpMapped<T>(this T input, IDictionary<string, string> mappings)
        {
            var expando = (IDictionary<string, object>)Util.ToExpando(input);
            foreach (var kvp in mappings)
            {
                // Don't ovewrite existing keys (for the timebeing)
                if (!expando.ContainsKey(kvp.Value))
                {
                    var val = expando[kvp.Key];
                    expando.Remove(kvp.Key);
                    expando[kvp.Value] = val;
                }
            }
            expando.Dump();
        }
    }
    

    ...which produces:

    Thank you also, SGM, for highlighting Util.CreateXhtmlWriter() which I will definitely use in the future!

    Best regards

    John

  • Options

    Having said that.... my example doesn't work everywhere, or indeed for nesting. When trying to use this on Util.Dif you just get an MemberDifNode (?) back as an expando so at the moment I'm jumping back out if it's an IDifResult.

    For nesting the SGM method has the advantage of going through all of the output and does pick up nested members.

        public static void DumpMapped<T>(this T input, IDictionary<string, string> mappings)
        {
            if (input is Util.IDifResult)
            {
                input.Dump();
                return;
            }           
    
            var expando = (IDictionary<string, object>)Util.ToExpando(input);
            foreach (var kvp in mappings)
            {
                // Don't overwrite existing keys (for the timebeing)
                if (expando.ContainsKey(kvp.Key) && !expando.ContainsKey(kvp.Value))
                {
                    var val = expando[kvp.Key];
                    expando.Remove(kvp.Key);
                    expando[kvp.Value] = val;
                }
            }
            expando.Dump();
        }
    

    Will think on this some more.

  • Options
    edited December 2023

    Why not respect System.ComponentModel.DataAnnotations.DisplayAttribute?

    • or perhaps a LINQPad-specific DumpNameAttribute?
      (also, DisplayFormatAttribute could be useful)
Sign In or Register to comment.