Add support for registering a service implementing multiple interfaces
Unfortunately Jab does not currently allow the registration of services implementing multiple interfaces (similar to how MEDI allows for registering a service that implements multiple interfaces).
I would very much like if this option was added. I have multiple instances of where a single service class implements multiple interfaces that I am using
As far as I know, the way you would do it with MEDI is the same as Jab with a common instance or factory for registration. It is more difficult comparatively to extend Jab for more complex registration scenarios though. I wonder if it would be possible to extend it at the source generation level without spending too much time.
public class MyClass : IMyInterface1, IMyInterface2;
public interface IMyInterface1;
public interface IMyInterface2;
public interface IMyInterface3;
public interface IMyInterface4;
public class MyClass2 : IMyInterface3, IMyInterface4;
public interface IMyInterface5;
public interface IMyInterface6;
public class MyClass3 : IMyInterface5, IMyInterface6;
public static class MediExtensions
{
public static IServiceCollection AddSingletonAs<TImpl>(
this IServiceCollection services,
IEnumerable<Type> interfaces
) where TImpl : class
{
services.AddSingleton<TImpl>();
foreach (var interf in interfaces)
{
services.AddSingleton(interf, sp => sp.GetRequiredService<TImpl>());
}
return services;
}
}
[ServiceProvider]
[Singleton<MyClass>]
[Singleton<IMyInterface1>(Factory = nameof(GetMyClass))]
[Singleton<IMyInterface2>(Factory = nameof(GetMyClass))]
[Singleton<IMyInterface3>(Instance = nameof(GetMyClass2))]
[Singleton<IMyInterface4>(Instance = nameof(GetMyClass2))]
[Singleton<MyClass3>]
[Singleton<IMyInterface5, MyClass3>]
[Singleton<IMyInterface6, MyClass3>]
public partial class MyContainer
{
public MyClass GetMyClass(MyClass myClass) => myClass;
public MyClass2 GetMyClass2 = new MyClass2();
}
public class Sample
{
[Fact]
public void JabTest_FactoryAndInstance()
{
var container = new MyContainer();
var instance1 = container.GetRequiredService<IMyInterface1>();
var instance2 = container.GetRequiredService<IMyInterface2>();
Assert.True(instance1 == instance2);
var instance3 = container.GetRequiredService<IMyInterface3>();
var instance4 = container.GetRequiredService<IMyInterface4>();
Assert.True(instance3 == instance4);
}
[Fact]
public void MediTest_FactoryAndInstance()
{
var services = new ServiceCollection();
MyClass MyClassFactory(IServiceProvider sp) => sp.GetRequiredService<MyClass>();
services
.AddSingleton<MyClass>()
.AddSingleton<IMyInterface1>(MyClassFactory)
.AddSingleton<IMyInterface2>(MyClassFactory);
var myClass2 = new MyClass2();
services
.AddSingleton<IMyInterface3>(myClass2)
.AddSingleton<IMyInterface4>(myClass2);
var provider = services.BuildServiceProvider();
var instance1 = provider.GetRequiredService<IMyInterface1>();
var instance2 = provider.GetRequiredService<IMyInterface2>();
Assert.True(instance1 == instance2);
var instance3 = provider.GetRequiredService<IMyInterface3>();
var instance4 = provider.GetRequiredService<IMyInterface4>();
Assert.True(instance3 == instance4);
}
[Fact]
public void MediTest_IntuitiveButWrongSyntax()
{
var services = new ServiceCollection();
services
.AddSingleton<MyClass>()
.AddSingleton<IMyInterface1,MyClass>()
.AddSingleton<IMyInterface2,MyClass>();
var provider = services.BuildServiceProvider();
var instance1 = provider.GetRequiredService<IMyInterface1>();
var instance2 = provider.GetRequiredService<IMyInterface2>();
Assert.False(instance1 == instance2);
}
[Fact]
public void JabTest_IntuitiveButWrongSyntax()
{
var container = new MyContainer();
var instance5 = container.GetRequiredService<IMyInterface5>();
var instance6 = container.GetRequiredService<IMyInterface6>();
Assert.False(instance5 == instance6);
}
[Fact]
public void MediTest_WithExtension()
{
var services = new ServiceCollection();
services.AddSingletonAs<MyClass>([typeof(IMyInterface1), typeof(IMyInterface2)]);
var provider = services.BuildServiceProvider();
var instance1 = provider.GetRequiredService<IMyInterface1>();
var instance2 = provider.GetRequiredService<IMyInterface2>();
Assert.True(instance1 == instance2);
}
}
I requested a similar feature in #133 a long time ago. Then, went on and wrote my own source generator which has this feature. Here is the relevant README section if you want to check out.