0

I want to inject a IDictionary of {key, interface} into a contructor, but I have no idea how to set it up in the program.cs

I can initiate the Interfaces and I can could initiate an IDictionary but I have no idea how to combine them.

Any suggestions would be appriciated.

Additional Context:

So i need to inject my services like

I need to inject the services eg,

s.AddTransient<IFooService, AFooService>();
s.AddTransient<IFooService, BFooService>();

but in the contructor I want

public MyClass(IDictionary<string, IFooService> fooServices)
EnenDaveyBoy
  • 119
  • 2
  • 9
  • `services.AddSingleton(myDictionary);`? Why do you want to do that in the first place though? – Panagiotis Kanavos Sep 08 '22 at 14:52
  • 2
    You shouldn't register a generic collection interface as a service. Why can't you define a normal service interface? – Dai Sep 08 '22 at 14:52
  • What would a dictionary of interfaces contain in the first place? If you mean to store interface types, you'd have to use a `Dictionary`. There's no way to say the types are interface, nor would it make a lot of sense. You can't instantiate instances of an interface. If you want to store instances that implement a specific interface you'd need `Dictionary`. – Panagiotis Kanavos Sep 08 '22 at 14:54
  • 2
    This sounds like an [XY Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). You have a problem X and assume Y is the solution (registering a dictionary of .... something). When that doesn't work, you ask for Y, not the real problem X. What is X here? Would it be solved if you registered services by name? That's already supported – Panagiotis Kanavos Sep 08 '22 at 14:55
  • I have added a bit more to the op, but i don't know how add the interfaces to a dictionary to inject it. – EnenDaveyBoy Sep 08 '22 at 15:22
  • 1
    @EnenDaveyBoy what does `string` represent here? – Guru Stron Sep 08 '22 at 17:49

2 Answers2

3
services.AddTransient<MyClass>();
services.AddTransient<AFooService>();
services.AddTransient<BFooService>();

services.AddTransient<IDictionary<string, IFooService>>(sp =>
    new Dictionary<string, IFooService>
    {
        { "A", sp.GetRequiredService<AFooService>() },
        { "B", sp.GetRequiredService<BFooService>() },
    });
``
Steven
  • 166,672
  • 24
  • 332
  • 435
1

A bit intrusive alternative is to add a key property to IFooService. Then you can have MEDI enumerate services:

interface IFooService
{
    string FooKey { get; }
    // ... void Work(); ...
}

class MyClass
{
    private IDictionary<string, IFooService> fooServices;

    public MyClass(IEnumerable<IFooService> fooServices) 
    {
        this.fooServices = fooServices.ToDictionary(foo => foo.FooKey);
    }
}

class Startup
{
    public void Configure(IServiceCollection s) 
    {
        // you can keep the initialization as-is. DI will populate IEnumerable
        s.AddTransient<IFooService, AFooService>();
        s.AddTransient<IFooService, BFooService>();
    }
}

I like this approach because my app performs DI registration via reflection, so adding another IFooService is as simple as adding a new class file.

snipsnipsnip
  • 2,268
  • 2
  • 33
  • 34