Our last post, “Building A Helper For XML Generation In C# & .NET”, looked at how to build a generic helper class that transparently serializes passed classes to XML.

In this post, we will look at how to use extension members to make it simpler and more discoverable.

The helper class looked like this:

using System.Text;
using System.Xml;
using System.Xml.Serialization;

public static class ResultEx
{
    public static async Task<IResult> Xml<T>(T value)
    {
        return Results.Text(await Serialize(value), "application/xml", Encoding.UTF8);
    }

    private static async Task<string> Serialize<T>(T value)
    {
        var serializer = new XmlSerializer(typeof(T));
        await using var ms = new MemoryStream();
        await using (var writer = XmlWriter.Create(
                         ms,
                         new XmlWriterSettings
                         {
                             Encoding = Encoding.UTF8,
                             Indent = true,
                             Async = true
                         }))
        {
            serializer.Serialize(writer, value);
        }

        return Encoding.UTF8.GetString(ms.ToArray());
    }
}

We can build on this by using extension members to extend the Results type.

The new class looks like this:

using System.Net.Mime;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

public static class ResultEx
{
    extension(Results)
    {
        public static async Task<IResult> Xml<T>(T value)
        {
            return Results.Text(await Serialize(value), MediaTypeNames.Text.Xml, Encoding.UTF8);
        }

        private static async Task<string> Serialize<T>(T value)
        {
            var serializer = new XmlSerializer(typeof(T));
            await using var ms = new MemoryStream();
            await using (var writer = XmlWriter.Create(
                             ms,
                             new XmlWriterSettings
                             {
                                 Encoding = Encoding.UTF8,
                                 Indent = true,
                                 Async = true
                             }))
            {
                serializer.Serialize(writer, value);
            }

            return Encoding.UTF8.GetString(ms.ToArray());
        }
    }
}

Here, we have created a static extension method, as we did in the post “Creating Static Extension Methods In C# & .NET”, to extend the Result class.

We can now do the following:

app.MapGet("/Generate", () =>
{
    var faker = new Faker<Person>().UseSeed(0)
        .RuleFor(person => person.FirstName, faker => faker.Person.FirstName)
        .RuleFor(person => person.Surname, faker => faker.Person.LastName)
        .RuleFor(person => person.Salary, faker => faker.Random.Decimal(10_000, 99_000));

    return Results.Xml(faker.Generate(5));
});
app.Run();

Here, we can see the Results class now has an XML method, to which we pass the class(es) to serialize.

TLDR

We can extend the Results class using extension members to add the capacity to serialize to XML.

The code is in my GitHub.

Happy hacking!