简体   繁体   中英

Onion architecture : respecting dependencies in the MVC Layer of the application

I am making a website using ASP.NET MVC and an onion architecture. I have the following architecture:

  1. Domain : Entities / Domain Interfaces
  2. Repository : Generic repository (for now) using Entity Framework Code First Approach
  3. Service : Generic Service that calls the Repository
  4. MVC

Now I am trying to create a method in my controller to start testing the methods I have implemented in Repository and Service , and I am having a hard time as to what I am allowed to create in this controller. I want to test a simple Get method in the Repository , but to do that I need GenericService object and GenericRepository object in my controller. To demonstrate what I mean here's a snippet of my GenericRepository(I will skip the interfaces):

public class GenericRepository<T> : IGenericRepository<T> where T : class
{
    private readonly PrincipalServerContext context;
    private DbSet<T> entities;
    public Repository(PrincipalServerContext context)
    {
        this.context = context;
        entities = context.Set<T>();
    }
}

Now my GenericService:

public class GenericService<T> : IGenericService<T> where T : class
{
    private IRepository<T> repository;

    public GenericService(IRepository<T> repository)
    {
        this.repository = repository;
    }
    public T GetEntity(long id)
    {
        return repository.Get(id);
    }
}

And finally, my question, am I allowed to create these objects in my controller as follows (using my dbcontext called PrincipalServerContext):

public class NavigationController : Controller
{
    private IGenericService<DomainModelClassHere> domainService;
    private IGenericRepository<DomainModelClassHere> domainRepo;
    private PrincipalServerContext context;

    public ActionResult MyMethod(){
        context = new PrincipalServerContext();
        domainRepo = new GenericRepository<DomainModelClassHere>(context);
        domainService = new GenericService<DomainModelClassHere>(domainRepo);
        if(domainService.GetEntity(1)==null)
           return View("UserNotFound");//Just as an example
        return View();
    }
}

Is this allowed? According to Jeffrey Palermo, UI can depend on Service and Domain so I don't know about the Repository . Technically I am not using methods from repository , but I do need to add a reference to the project.

If I can't then how can I create a new GenericService if I don't have a GenericRepository ? Is there a better way to instantiate my objects ?

EDIT I think the answer to my question resides in Startup.cs where I can put something like service.addScoped(typeof(IGenericRepository<>),typeof(GenericRepository<>)); but I 'm not sure about this, any ideas?

I'll answer this on my own if ever someone encounters the same problem. There are configuration methods we can use to create instances of classes when needed. In the Startup.cs file you have to add ConfigureServices(IServiceCollection services) method and inside there are several methods that can be applied to services to create these instances. For example you can use:

services.AddTransient(IGenericRepository, GenericRepository)

What is the difference between services.AddTransient, service.AddScope and service.AddSingleton methods in Asp.Net Core 1? (this link explains differences between methods).

AddTransient is good in my case because it creates an instance of an object through the whole lifespan of the application, which is what I need. This means UI is dependant on the rest of the solution, because Startup.cs needs to know about the Repositories as well as the Services . A pretty good answer can be found here : Onion Architecture : Can UI depend on Domain .

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