Developer's format helpers

Karen Payne - Jul 7 - - Dev Community

Introduction

Learn how to provide assistance for allowing other developers to specify formatting of objects from your code no different than Intellisense in Microsoft Visual Studio.

Applies to

Product Version
.NET 7,8,9

Sample project

Samples overview

Using Entity Framework Core (but not limited to EF Core), read data using the following model.

public partial class BirthDay
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateOnly? BirthDate { get; set; }
    // computed column
    public int? YearsOld { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

To produce the following output.

Shows output

This is done by hardcoding each properties format e.g. D2, MM/dd/yyyy

Using the following code.

public static async Task Conventional()
{
    await using var context = new Context();
    var list = await context.BirthDays.ToListAsync();

    foreach (var item in list)
    {
        // line broken for readability
        Debug.WriteLine($"{item.Id,-5:D2}" +
                        $"{item.FirstName,-15}" +
                        $"{item.LastName,-15}" +
                        $"{item.BirthDate!.Value,-12:MM/dd/yyyy}" +
                        $"{item.YearsOld!.Value:D3}");
    }
}
Enter fullscreen mode Exit fullscreen mode

StringSyntaxAttribute Class

The StringSyntaxAttribute class provides the ability to allow the caller to a method to specify their own format e.g. rather than D2, D5 etc.

Revised code from the first code sample.

StringSyntax(NumericFormat) means to present number formats.

Dropdown with number formats

StringSyntax(DateOnlyFormat) means to present DateOnly formats.

Shows Dropdown for DateOnly formats

public static async Task Syntax(
    [StringSyntax(NumericFormat)] string iDFormat,
    [StringSyntax(DateOnlyFormat)] string dateFormat,
    [StringSyntax(NumericFormat)] string ageFormat)
{

    await using var context = new Context();
    var list = await context.BirthDays.ToListAsync();

    foreach (var item in list)
    {
        // line broken for readability
        Debug.WriteLine($"{item.Id.ToString(iDFormat),-5}" +
                        $"{item.FirstName,-15}" +
                        $"{item.LastName,-15}" +
                        $"{item.BirthDate!.Value.ToString(dateFormat),-12}" +
                        $"{item.YearsOld!.Value.ToString(ageFormat)}");
    }
}
Enter fullscreen mode Exit fullscreen mode

Other formats supported

  • DateTimeFormat
  • EnumFormat
  • GuidFormat
  • Json
  • Regex
  • TimeOnlyFormat
  • TimeSpanFormat
  • Uri
  • Xml

Create your own

Another idea is to setup formatting from a source such as appsettings.json

In the following example the formats are in appsettings.json.

{
  "ApplicationSetting": {
    "IdentifierFormat": "D2",
    "DateOnlyFormat": "MM/dd/yyyy",
    "AgeFormat": "D3"
  } 
}
Enter fullscreen mode Exit fullscreen mode

Using the following model.

public class ApplicationSetting
{
    public string IdentifierFormat { get; set; }
    public string AgeFormat { get; set; }
    public string DateOnlyFormat { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

In the provided code sample the following is used to get our formats.

public static ServiceCollection ConfigureServices()
{
    static void ConfigureService(IServiceCollection services)
    {

        services.Configure<ConnectionStrings>(Config.Configuration.JsonRoot()
            .GetSection(nameof(ConnectionStrings)));

        services.Configure<EntityConfiguration>(Config.Configuration.JsonRoot()
            .GetSection(nameof(EntityConfiguration)));

        services.Configure<ApplicationSetting>(Config.Configuration.JsonRoot()
            .GetSection(nameof(ApplicationSetting)));

        services.AddTransient<SetupServices>();
    }

    var services = new ServiceCollection();
    ConfigureService(services);

    return services;

}
Enter fullscreen mode Exit fullscreen mode

Create out own Attribute to store multiple formats.

internal class Samples
{
    /// <summary>
    /// Get formats from appsettings.json, see <see cref="SetupServices"/>
    /// </summary>
    [AttributeUsage(AttributeTargets.Parameter)]
    public class AppSyntaxAttribute : Attribute
    {
        public static string IdentifierFormat = FormatSettings.Instance.Items.IdentifierFormat;
        public static string AgeFormat = FormatSettings.Instance.Items.AgeFormat;
        public static string DateOnlyFormat = FormatSettings.Instance.Items.DateOnlyFormat;
    }

    public async Task SpecialSyntax([AppSyntax()] string numbers = "")
    {
        var idFormat = AppSyntaxAttribute.IdentifierFormat;
        var dateFormat = AppSyntaxAttribute.DateOnlyFormat;
        var yearsOldFormat = AppSyntaxAttribute.AgeFormat;

        await using var context = new Context();
        var list = await context.BirthDays.ToListAsync();

        foreach (var item in list)
        {
            // line broken for readability
            Debug.WriteLine($"{item.Id.ToString(idFormat),-5}" +
                            $"{item.FirstName,-15}" +
                            $"{item.LastName,-15}" +
                            $"{item.BirthDate!.Value.ToString(dateFormat),-12}" +
                            $"{item.YearsOld!.Value.ToString(yearsOldFormat)}");


        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Summary

Code has been presented to provide a single developer or a team of developers to have intellisense for method parameters.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .