1

I'm using the latest version of Unity, (3.5.1405-prerelease), for injecting dependencies, (three layer architecture).

Project.Web

Application layer, MVC.

App_Start:

public static class UnityWebActivator
{
    public static void Start() 
    {
        var container = UnityConfig.GetConfiguredContainer();

        FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
        FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));

        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
    }

    public static void Shutdown()
    {
        var container = UnityConfig.GetConfiguredContainer();
        container.Dispose();
    }
}

public class UnityConfig
{
    #region Unity Container
    private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
    {
        var container = new UnityContainer();
        RegisterTypes(container);
        return container;
    });

    public static IUnityContainer GetConfiguredContainer()
    {
        return container.Value;
    }
    #endregion

    public static void RegisterTypes(IUnityContainer container)
    {
        container.RegisterType<IAccountService, AccountService>();
        container.RegisterType<IAdministrationService, AdministrationService>();
    }
}

Project.Business

Business layer, class library. Contains service.

Project.Data

Data layer, class library. Contains repository.

Question

How do I register types for my data layer? Currently it's only registrating Application layer -> Business layer. I dont want to register business layer -> data layer within my application layer.

Update 1 - Example

This is an example for when I want to retrieve a userID from the database.

APPLICATION LAYER:

public class HomeController : Controller
{
    private readonly IUserService _userService;

    public HomeController(IUserService userService)
    {
        _userService = userService;
    }

    [HttpGet]
    public ActionResult GetUserID()
    {
        int userID = _userService.GetUserIDGuest("test@gmail.com");

        return View(userID);
    }
}

SERVICE LAYER:

public class UserService : IUserService
    {
        private readonly IUserRepository _userRepository;

        public UserService(IUserRepository userRepository)
        {
            _userRepository = userRepository;
        }

        public int GetUserIDGuest(string email)
        {
            return _userRepository.GetUserIDGuest(email);
        }
}

DATA LAYER:

    public abstract class RepositoryBase
    {
        protected readonly DataLayer DB;
        protected readonly CloudStorageServices Storage;

        protected RepositoryBase(DataLayer db, CloudStorageServices storage)
        {
            DB = db;
            Storage = storage;
        }
    }

public class UserRepository : RepositoryBase, IUserRepository
{
    public UserRepository(DataLayer db, CloudStorageServices storage) : base(db, storage) { }

    public int GetUserIDGuest(string email)
    {
        return DB.User.Where(m => m.Email == email.ToLower().Trim() && m is Guest).Select(o => o.UserID).SingleOrDefault();
    }
}
Reft
  • 2,333
  • 5
  • 36
  • 64
  • What do you mean by the -> symbol here? Also, in your question you say "how **do** I register..." , and then you say "I **don't** want to register...". Can you please explain? – Yacoub Massad Oct 04 '15 at 11:45
  • application layer -> service layer -> data layer. The communcation flow. Currently the service layer types are registered in the application, which is correct. The problem im facing is how to register types for the data layer, service layer -> data layer. I need to create a class for this in the service layer, which i don't know how to do. So the service types should be registered in the application layer, and the data types should be registered in the service layer, (not application layer). – Reft Oct 04 '15 at 11:52
  • 1
    Why would you think that? Everything should be registered in the application layer. Actually, everything should be registered in the [Composition Root](http://blog.ploeh.dk/2011/07/28/CompositionRoot/) which lives in the application layer. Can you give an example of a data layer class that you want to register? Usually, you don't register data entities because they are not services. Usually, you use `new` to create instances of data entities (e.g. Customer) – Yacoub Massad Oct 04 '15 at 11:58
  • But my app.layer has reference to service.layer, and the service.layer and reference to data.layer. If I were to register all types in the application, i'll have to add reference from application.layer to data.layer, which I dont think you are supposed to do, (defeats the purpose of using n-tier solutions). I will update my question with an example! – Reft Oct 04 '15 at 12:04
  • It depends. If you think of the service layer as a stand-alone application that can live by it self, then you can consider it an application and give it its own composition root. However, if you think that it is not considered an application by it self, then you should compose everything in the composition root in the application layer even if that means that you should reference the data layer from the application layer. – Yacoub Massad Oct 04 '15 at 12:14
  • 1
    Related: https://stackoverflow.com/questions/9501604/ioc-di-why-do-i-have-to-reference-all-layers-assemblies-in-entry-application – Steven Oct 04 '15 at 13:28

1 Answers1

1

It seems to me from the examples you provided the that service layer is a simple set of classes that will live in the same process/application of your ASP.NET site (i.e. it is not a complete application that runs in its own process).

This means that your service layer does not constitute an application by it self.

You should register everything (e.g. IUserService, IUserRepository, DataLayer, and CloudStorageServices) at the Composition Root of your ASP.NET application, even if that means that your application will reference all the other class libraries.

This is fine, the application itself needs to reference everything, its where you put the pieces of the puzzle together.

It is the class libraries that should not reference everything and only reference other class libraries that contain the abstractions or other types that they depend on.

Quoting from the article I referenced (Composition Root):

Only applications should have Composition Roots. Libraries and frameworks shouldn't.

Yacoub Massad
  • 27,509
  • 2
  • 36
  • 62
  • So it's not possible to create another class in the service layer that registers my data layer types (with Unity)? Where I work they use the same kind of structure, but instead of Unity they use Ninject. In their application layer they have this "ApplicationInjectionModule" class which inherits from NinjectModule and override the load method. Same kind of class also exists in the service layer, "DomainInjectionModule", but instead it registers repository classes instead of service layer classes. – Reft Oct 04 '15 at 12:35
  • The answer in [this question](http://stackoverflow.com/questions/3427674/can-i-register-my-types-in-modules-in-unity-like-i-can-in-autofac) suggest that there isn't a way to do that in unity. But the question is from 2010 and things might have changed since then. I myself have not seen such a feature in Unity. However, what I am suggesting in my answer is that you don't do this and instead do everything in the composition root ( in the application layer). However, if this is what you need to do where you work then this is what you need to do :) – Yacoub Massad Oct 04 '15 at 12:46
  • Another answer in the referenced question suggests another way to do it. You might want to check that out. – Yacoub Massad Oct 04 '15 at 12:50
  • Alright, big thanks for the help! I will wait a couple of hours and if there are no other suggestions I will accept your answer. – Reft Oct 04 '15 at 12:57