简体   繁体   中英

Dependency injection : how do i resolve multiple instances at runtime?

I am using Simple Injector for my injection fun.

As far as, I understand I only register and resolve with my container on my bootstrapper project.

So I have this code in my console application :

static void Main(string[] args)
{
    Container container = ComposeRoot();

    var controller = container.GetInstance<IBussinesLogicController>();
    controller.Execute();

    Console.WriteLine("Started");
    Console.ReadLine();
}

private static Container ComposeRoot()
{
    var container = new Container();

    //Bussines Logic controllers.
    container.Register<IBussinesLogicController, BussinesLogicController>(Lifestyle.Singleton);
    container.Register<IStationController, StationController>(Lifestyle.Transient);

    //Data Access controllers.
    container.Register<IDataAccessController, DataAccessController>(Lifestyle.Singleton);
    container.Register<IDirectoryStructureController, DirectoryStructureController>(Lifestyle.Singleton);

    //Shared controllers.
    container.Register<ILogger, LoggerController>(Lifestyle.Singleton);

    container.Verify();

    return container;
}

This will resolve my businesslogic controller and call Execute.

Now in execute I want to resolve 10 new instances of IStationController and add them to a list.

var stations = new List<IStationController>();
for (int i = 0; i < 10; i++)
{
    //Resolve IStationController here...
    //IStationController station = diContainer.GetInstance<IStationController>();
    //station.StationName = $"Station {i}";
    //stations.Add(station);
}

How can i do this properly, since my Business Logic project does not and is not allowed a reference to the dependency container?

I can resolve this easily by adding the dependency to the container but am afraid i am not following the correct patterns.

My solution layout is as follows :

  • Class Library (DAL)
  • Class Library (BLL) <- IBussinesLogicController
  • Class Library (Models)
  • Class Library (Logger)
  • Console Application (ConsoleApp6) <- ComposeRoot()

Please let me know what the right approach is to this problem.

Thanks!

You can register a factory delegate and use it in your class.

Register the delegate as follows:

container.Register<IStationController, StationController>(Lifestyle.Transient);
container.RegisterSingleton<Func<IStationController>>(
    () => container.GetInstance<IStationController>());

And inject it to your BussinesLogicController constructor:

public BussinesLogicController (Func<IStationController> stationControllerFacrtory)

And you use it in the loop:

List<IStationController> stations = new List<IStationController>();
for (int i = 0; i < 10; i++)
{
    //Resolve IStationController here...
    IStationController station = this.stationControllerFactory.Invoke();
    station.StationName = $"Station {i}";
    stations.Add(station);
}   

Reviewing the documentation for the Simple Injector , have a look at the following link , which details the seamless implementation of the Dependency Injection for the ASP.Net MVC, where the DI framework takes care of resolving the dependency at the run-time. I am making an assumption that you are working with an MVC controller

Pasting the relevant code and customizing:

Application Start event

using System.Web.Mvc;
using SimpleInjector;
using SimpleInjector.Integration.Web.Mvc;

public class Global : System.Web.HttpApplication {

    protected void Application_Start(object sender, EventArgs e) {
        // 1. Create a new Simple Injector container
        var container = new Container();

        // 2. Configure the container (register)
        // See below for more configuration examples
        container.Register<IStationController, StationController>(Lifestyle.Transient);

        // 3. Optionally verify the container's configuration.
        container.Verify();

        // 4. Store the container for use by the application
        DependencyResolver.SetResolver(
            new SimpleInjectorDependencyResolver(container));
    }
}

Basic Controller

using System;
using System.Web.Mvc;

public class BusinessLogicController : Controller {
    private readonly IStationController stationController;

    public BusinessLogicController(IStationController stationController) {
        this.stationController = stationController;
    }

    // Use the IStationController object in various calls
}

Important (From documentation):

In the case of MVC, the fifth step (resolving the instance) is the responsibility of the MVC framework. For each received web requests, the MVC framework will map that request to a Controller type and ask the application's IDependencyResolver to create an instance of that controller type. The registration of the SimpleInjectorDependencyResolver (part of the SimpleInjector.Integration.Web.Mvc.dll) will ensure that the request for creating an instance is forwarded on to Simple Injector. Simple Injector will create that controller with all of its nested dependencies.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM