0

I would like to use Microsoft's dependency injection extension to achieve DI. I have created a simple console application to test out my understanding. I have 2 objects, Dog and Cat both have a interface IAnimal. Very simple setup. I wanted to use AddTranient<IAnimal, Dog> and AddTranient<IAnimal, Cat> to create the service that houses my Dog and Cat object. Later when I retrieve objects, I am running into issues using GetRequiredService(). It only returns the last object Cat. See below code using .Net 6. How do I retrieve Dog object when I needed and vise versa for Cat object?

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddTransient<IAnimal, Dog>();
builder.Services.AddTransient<IAnimal, Cat>();

using IHost host = builder.Build();

var myobject = GetAnimalObject(host.Services, "Scope 1");
Console.WriteLine($"Name: {myobject.name}");
await host.RunAsync();

static IAnimal GetAnimalObject(IServiceProvider services, string scope)
{
    using IServiceScope serviceScope = services.CreateScope();
    IServiceProvider provider = serviceScope.ServiceProvider;
    var result = provider.GetRequiredService<IAnimal>();
    return result;
}

public sealed class Dog : IAnimal
{
    public string name { get; set; } = "Daug";
}

public sealed class Cat : IAnimal
{
    public string name { get; set; } = "Kate";
}

public interface IAnimal
{
    string name { get; set; }
}

I tried GetRequiredService and GetRequiredService but both returned null.

  • Register it as IDog. You might also have an interface segregation problem if you need a specific need – Daniel A. White Jul 24 '23 at 21:59
  • 1
    Is the object being disposed at the end of GetAnimalObject? Generally I don't like returning a reference to an object whose when its scope is being disposed. Either use it in method, or refactor your code to get your scope where you use it. Both Dog and Cat can be registered as IAnimal, first instance registered will be returned so will be Dog in this example. If you used constructor injection IEnumerable would return all registered instances. Simple breakpoint in GetAnimalObject method will tell you if that is in fact happening. – Anthony G. Jul 24 '23 at 22:52

1 Answers1

1

It's normal for .NET's DI to return the last registered service. This allows other services to "override" the previous services.

To get all services for an interface, call GetServices<IAnimal> instead of GetRequiredService<IAnimal>. GetServices will return an IEnumerable<IAnimal> of all the services.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810