0

I have been attempting to get Lamar working for our dependency injection, but my lack of experience doing so has been causing me some grief.

I have a simple dummy controller:

[Route("[controller]")]
public class TestController : Controller
{
    [HttpGet]
    public int GetRandom()
    {
        TestService service = new TestService();
        int value = service.GetRandomNumber();


        return value;
    }
}

Inside of TestService is an interface'd repository, where I would like the DI to apply to.

I've added UseLamar to my Program.cs, and my startup.cs looks like this:

    public void ConfigureContainer(ServiceRegistry services)
    {
        services.AddMvc();
        services.Scan(s =>
        {
            s.Assembly("Test.Components");
            s.WithDefaultConventions();
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Invalid");
        });

        app.UseMvc();
    }

From reading the documentation I believe that Lamar should automatically map my Interface to my type, as they have the same name (IRepository -> Repository), though thats not what I am seeing.

I'm very sure I've missed something, but I've been over the documentation and have been attempting to google around for real examples to no avail. Is there some lines I am missing in Startup.cs? Does my Service need a constructor to set the Repository?

Blankdud
  • 698
  • 5
  • 9
  • 22

1 Answers1

1

Generally speaking, you want to inject your dependencies via the constructor. There are cases where you might take another approach, but constructor injection is the way to go in 90%+ of cases in my experience.

So indeed you would want to add IRepository to your TestService constructor. However, from your code it looks like you are missing something more fundamental about the way dependency injection works.

TestService service = new TestService();

When you use new to create an object, you are controlling the lifecycle and scope of that object. The point of using a dependency injection framework is to let it (the framework/container) manage dependencies and their scope/lifecycle for you. If you instantiate an object using a dependency injection container, it resolves the dependencies of that object for you--it also manages the dependencies of those dependencies as well, and so on, so that you can have a chain of dependencies that get resolved without working through the complexities of initializing a large object graph manually (using "new").

To solve your immediate question, you could do something like (this is bad code--not recommended!):

TestService service = container.Resolve<ITestService>();

The container would be the lamar container where you register your types--I'm not familiar with lamar so the Resolve() syntax might look slightly different. This would resolve the TestService and would inject a Repository and all constructor arguments of the TestService class.

The preferred way to do this is to resolve the dependency chain at the boundary (entry point) of your application, which is your controller itself. So your controller should accept an ITestService as a constructor argument, and the container/framework would resolve TestController => TestService => Repository.

There is a bit of wiring you need to do to get this to work. As I said, I don't know lamar, so I'm not sure how to get that to work with Asp.net Core.

In Asp.Net Framework WebAPI, it would look something like this using Unity for DI:

GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new UnityControllerActivator(container));

This code would run as your application starts up, and tells the ASP.Net framework: when a request comes in resolve the appropriate controller and all of its dependencies using the provided container.

Phil Sandler
  • 27,544
  • 21
  • 86
  • 147
  • Question - The IServicesCollection.AddLamar method doesn't take an Container object. In fact, I can only get it to take-in ServiceRegistry references. As such, how do you get IContainer from the ServiceProvider given that this is .NET Core? – Prisoner ZERO Aug 15 '22 at 18:01