Search code examples
entity-frameworkdependency-injectionrepository-patternioc-containersimple-injector

Register a container (IoC) in a class library?


I'm creating an n-tier application with the following sections.

  • MyApp.DAL - data access layer (EF 5, SQL back end)
  • MyApp.BLL - business layer
  • MyApp.WcfService - Services layer
  • MyApp.WpfClient - front end
  • MyApp.Models is a shared project that holds all of the POCOs.

I'll give an example of the "Country" entity through each layer. First is the model. Please note that StatefulObject will help me track an entity sate from the disconnected client (per Julia Lerner's programming EF 2nd edition Chapter 18).

public class Country : StatefulObject
{
    [Key]
    [StringLength(2)]
    public string Code { get; set; }
    [Required]
    [StringLength(50)]
    public string Name { get; set; }
}

In the DAL I have an ICountryRepository (basic CRUD) and a CountryRepository. Here is the constructor.

public class CountryRepository : ICountryRepository, IDisposable
{
    MyDbContext _db;

    public CountryRepository()
    {
        _db = new MyDbContext();
    }

    //Implement ICountryRepository (basically CRUD), etc...
}

My BLL has an ICountryLogic, CountryLogic, IBusinessLayer, and BusinessLayer like so:

public class CountryLogic : ICountryLogic
{
    ICountryRepository _countryRepository;

    public CountryLogic(ICountryRepository countryRepository)
    {
        _countryRepository = countryRepository;
    }

    //implement ICountryLogic members, etc...
}

public class BusinessLayer : IBusinessLayer
{
    public ICountryLogic CountryLogic { get; set; }

    public BusinessLayer()
    {
        CountryLogic = new CountryLogic(new CountryRepository());
    }
}

Then an example service method that instantiates a new Business layer and does some operation like so:

public class CountryService : ICountryService
{
    public IEnumerable<Country> GetAll()
    {
        IBusinessLayer bl = new BusinessLayer();
        return bl.CountryLogic.GetAll();
    }

    //implement other service operations
}

Then the WPF client can just use the service like so:

CountryServiceClient countryService = new CountryServiceClient();

var countries = countryService.GetAll();

Now, before putting the WCF service between the BLL and WPF front end, my WPF front end could just use Dependency Injections and I wouldn't have this ugliness:

public class BusinessLayer : IBusinessLayer
{
    public ICountryLogic CountryLogic { get; set; }

    public BusinessLayer()
    {
        CountryLogic = new CountryLogic(new CountryRepository());  // <<<< UGLY HERE
    }
}

Instead I would use DI and constructor injection like so:

public class BusinessLayer : IBusinessLayer
{
    public ICountryLogic CountryLogic { get; set; }

    public BusinessLayer(ICountryLogic countryLogic)
    {
        CountryLogic = countryLogic;
    }
}

Then just register the interfaces and implementations in the container in WPF. My question is how can I register them in the class library (in the BLL)? Since there is no composition root or entry point in a class library I'm not sure how to do it. I'm using SimpleInjector.

Alternatively, I could use DI in the Wcf service, but that would require the service to have a reference to the DAL so it could register the ICountryRepository to a CountryRepository. This doesn't seem right. The service layer should only reference the BLL, which is why I want the DI set up in the BLL. Thanks.


Solution

  • Perhaps you could try implement a static BootStrap method within each layer and chain the calls for registration (passing the container instance down through each method.

    Wpf.Client calls Wpf.Service.Bootstrap(container) which calls WPF.Bll.Bootstrap(container) ... ?

    This should get you going, but I heartily recommend you read through Stevens articles, they make a lot of sense and once implemented they provide a very flexible architecture.