I don't claim that this is production-ready, but you can hack it a bit by introducing an extension method such as `ThenByCustom` which just saves the `keySelector` and replaces it with `x => x`. The actual `keySelector` is used only when comparing values that have the same primary key in a custom comparer.

This is the idea:

```csharp
public static class Extensions {
    public static IOrderedEnumerable<TSource> ThenByCustom<TSource, TKey>(
        this IOrderedEnumerable<TSource> source,
        Func<TSource, TKey> keySelector) {
        var customComparer = new KeyComparer<TSource, TKey>(keySelector);
        return source.ThenBy(x => x, customComparer);
    }

    private class KeyComparer<TSource, TKey> : IComparer<TSource> {
        private readonly Func<TSource, TKey> _keySelector;
        private readonly IComparer<TKey> _keyComparer;

        public KeyComparer(Func<TSource, TKey> keySelector) {
            _keySelector = keySelector;
            _keyComparer = Comparer<TKey>.Default;
        }

        public int Compare(TSource x, TSource y) {
            return _keyComparer.Compare(_keySelector(x), _keySelector(y));
        }
    }
}
```

Your (slightly modified) example then:
```csharp
static void Main() {
    var data = new[]
    {
            new { Name = "Alice", Age = 30 },
            new { Name = "Charlie", Age = 25 },
            new { Name = "Bob", Age = 25 },
        };

    var sorted = data
        .OrderBy(x => Tracer("First criterion", x.Age))
        .ThenByCustom(x => Tracer("Second criterion", x.Name));

    foreach (var item in sorted) {
        Console.WriteLine($"{item.Name} - {item.Age}");
    }
}

static T Tracer<T>(string label, T value) {
    Console.WriteLine($"Computing {label} key: {value}");
    return value;
}
```

outputs

```
Computing First criterion key: 30
Computing First criterion key: 25
Computing First criterion key: 25
Computing Second criterion key: Charlie
Computing Second criterion key: Bob
Bob - 25
Charlie - 25
Alice - 30
```

if you make the age different, you'd see no Tracer calls for the second criterion.