Repository: microsoft/onefuzz
File: src/ApiService/ApiService/onefuzzlib/ImageOperations.cs (C#)

Code before:
        var publisher = imageParts[0];
        var offer = imageParts[1];
        var sku = imageParts[2];
        var version = imageParts[3];

        return new ImageInfo(Publisher: publisher, Offer: offer, Sku: sku, Version: version);
    }
}

public class ImageOperations : IImageOperations {
    private IOnefuzzContext _context;
    private ILogTracer _logTracer;
    private readonly IMemoryCache _cache;

    const string SubscriptionsStr = "/subscriptions/";
    const string ProvidersStr = "/providers/";


    public ImageOperations(ILogTracer logTracer, IOnefuzzContext context, IMemoryCache cache) {
        _logTracer = logTracer;
        _context = context;
        _cache = cache;
    }

    public Task<OneFuzzResult<Os>> GetOs(Region region, string image)
        => _cache.GetOrCreateAsync<OneFuzzResult<Os>>($"GetOs-{region}-{image}", entry => GetOsInternal(region, image));

    private async Task<OneFuzzResult<Os>> GetOsInternal(Region region, string image) {
        string? name = null;
        if (image.StartsWith(SubscriptionsStr) || image.StartsWith(ProvidersStr)) {
            var parsed = _context.Creds.ParseResourceId(image);
            parsed = await _context.Creds.GetData(parsed);
            if (string.Equals(parsed.Id.ResourceType, "galleries", StringComparison.OrdinalIgnoreCase)) {
                try {
                    // This is not _exactly_ the same as the python code  
                    // because in C# we don't have access to child_name_1
                    var gallery = await _context.Creds.GetResourceGroupResource().GetGalleries().GetAsync(
                        parsed.Data.Name
                    );

                    var galleryImage = gallery.Value.GetGalleryImages()
                        .ToEnumerable()
                        .Where(galleryImage => string.Equals(galleryImage.Id, parsed.Id, StringComparison.OrdinalIgnoreCase))
                        .First();

                    galleryImage = await galleryImage.GetAsync();

                    name = galleryImage.Data?.OSType?.ToString().ToLowerInvariant()!;

                } catch (Exception ex) when (
                      ex is RequestFailedException ||

Review comment (suggestion):
I've been using key classes for this, which helps to guarantee that we don't accidentally have a collision, e.g. `record class GetOsKey(Region Region, string Image);`

Code after:
        var publisher = imageParts[0];
        var offer = imageParts[1];
        var sku = imageParts[2];
        var version = imageParts[3];

        return new ImageInfo(Publisher: publisher, Offer: offer, Sku: sku, Version: version);
    }
}

public class ImageOperations : IImageOperations {
    private IOnefuzzContext _context;
    private ILogTracer _logTracer;
    private readonly IMemoryCache _cache;

    const string SubscriptionsStr = "/subscriptions/";
    const string ProvidersStr = "/providers/";


    public ImageOperations(ILogTracer logTracer, IOnefuzzContext context, IMemoryCache cache) {
        _logTracer = logTracer;
        _context = context;
        _cache = cache;
    }

    record class GetOsKey(Region Region, string Image);

    public Task<OneFuzzResult<Os>> GetOs(Region region, string image)
        => _cache.GetOrCreateAsync<OneFuzzResult<Os>>(new GetOsKey(region, image), entry => GetOsInternal(region, image));

    private async Task<OneFuzzResult<Os>> GetOsInternal(Region region, string image) {
        string? name = null;
        if (image.StartsWith(SubscriptionsStr) || image.StartsWith(ProvidersStr)) {
            var parsed = _context.Creds.ParseResourceId(image);
            parsed = await _context.Creds.GetData(parsed);
            if (string.Equals(parsed.Id.ResourceType, "galleries", StringComparison.OrdinalIgnoreCase)) {
                try {
                    // This is not _exactly_ the same as the python code
                    // because in C# we don't have access to child_name_1
                    var gallery = await _context.Creds.GetResourceGroupResource().GetGalleries().GetAsync(
                        parsed.Data.Name
                    );

                    var galleryImage = gallery.Value.GetGalleryImages()
                        .ToEnumerable()
                        .Where(galleryImage => string.Equals(galleryImage.Id, parsed.Id, StringComparison.OrdinalIgnoreCase))
                        .First();

                    galleryImage = await galleryImage.GetAsync();

                    name = galleryImage.Data?.OSType?.ToString().ToLowerInvariant()!;