The generic constraints where TService : class, IPingableService and where TImplementation : class, TService, IPingableService are checked at compile time, so TService itself must be (or extend) IPingableService, and TImplementation must implement both TService and IPingableService (BR-11).
Register TImplementation under TService with the requested lifetime (transient, scoped, or singleton) — e.g. services.AddTransient<TService, TImplementation>().
Register the forwarding factory services.AddTransient<IPingableService, TImplementation>(x => (TImplementation)x.GetRequiredService<TService>()) (substituting AddScoped/AddSingleton for the other two methods), with the same lifetime as step 2, so Provider.GetServices<IPingableService>() in OP-01 step 3 can find it. The factory does not create a second instance — it resolves TService from the same provider/scope and casts the result to TImplementation (BR-15).
For Transient, the forwarding factory still produces a fresh TImplementation instance per resolution (each GetRequiredService<TService>() call creates a new one), so TService and IPingableService resolutions are independent instances, consistent with transient semantics.
For Scoped, every resolution of IPingableService within a given scope shares the identical TImplementation instance that TService resolves to in that same scope — the forwarding factory already provides this identity sharing; a host never needs to add its own factory for it to work.
For Singleton, every resolution of IPingableService for the lifetime of the application shares the identical singleton instance that TService resolves to.
If a caller replaces the TService registration independently (bypassing AddPingable*, e.g. by calling services.AddScoped<TService, OtherImplementation>() afterward), the forwarding factory's cast (TImplementation)x.GetRequiredService<TService>() fails at ping time with an InvalidCastException, which surfaces as a 500 via BR-05 (BR-15).