Register container (IoC) in class library?

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

  • MyApp.DAL - Data Access Layer (EF 5, SQL end)
  • MyApp.BLL - business layer
  • MyApp.WcfService - Service Level
  • MyApp.WpfClient - front end
  • MyApp.Models is a collaborative project that contains all the POCOs.

I will give an example of a Country object across each layer. The first is the model. Please note that StatefulObject helps me keep track of entity entity from disconnected client (in Julia Lerner EF 2nd edition Chapter 18 program).

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

      

In DAL, I have ICountryRepository (basic CRUD) and 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 ICountryLogic, CountryLogic, IBusinessLayer and BusinessLayer:

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 creates a new business layer and performs some operation like this:

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 this:

CountryServiceClient countryService = new CountryServiceClient();

var countries = countryService.GetAll();

      

Now, before putting the WCF service between the BLL and WPF interface, my WPF interface can just use dependency injection 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 install the constructor like so:

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

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

      

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

Alternatively, I could use DI in the Wcf service, but this would require the service to have a DAL reference so that it can register the ICountryRepository with the CountryRepository. It doesn't seem right. The service layer should only refer to the BLL, so I want the DI to be configured in the BLL. Thank.

+3


source to share


2 answers


Perhaps you could try to implement a method static BootStrap

at each level and chain the calls to register (passing a container instance through each method.

Wpf.Client

calls Wpf.Service.Bootstrap(container)

, which calls WPF.Bll.Bootstrap(container)

...?



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

+3


source


As far as I can see, abstractions are missing here. The WPF client doesn't have to worry about hosting a WCF service in between. For example, instead of having some pretty ugly classes XXXService

(like CountryService

), consider sending commands and requests over the wire. This way you can define simple interfaces ICommandHandler<TCommand>

and IQueryHandler<TQuery, TResult>

that a WPF client can depend on. In this case, he does not need to know whether he is interacting over the network or not. These abstractions also make it possible to add crosscutting issues (like decorators) such as the circuit breaker circuit patternwhich is very useful when dealing with clients that have an unreliable connection (especially useful with queries). For sending commands, you might be better off with a queue, but this can be implemented as a decorator on the interface ICommandHandler<TCommand>

.

Here are some articles that describe these concepts:



+4


source







All Articles