1

I am new to architecture, I am in the process of learning and designing an application end to end. I have the below architecture and am using Autofac to manage object creation.

enter image description here

All businessobject contracts have been setup on webapi startup and that is the only startup which can actually startup all my autofac configurations/modules.

I use UnitOfWork/Repository pattern and it resides beyond my business layer, I do not want to refer the UnitOfWork in my WebAPi but i cannot startup UnitOfWork otherwise.

Can someone please give me some inputs on what should be my architecture/design/autofac unitofwork implementation?

Immortal
  • 1,233
  • 4
  • 20
  • 47
  • 1
    You should have all direct references on driver project (web api) otherwise you can't apply ioc, Because you have to manage lifetime in one place. – Erkan Demirel Apr 25 '16 at 07:31
  • @ErkanDemirel Thank you for your comment. Sure, i understand that, however, doesn't that means leaky architecture, having a reference to Repository in web api? – Immortal Apr 26 '16 at 00:08
  • Possible duplicate of [Ioc/DI - Why do I have to reference all layers/assemblies in entry application?](http://stackoverflow.com/questions/9501604/ioc-di-why-do-i-have-to-reference-all-layers-assemblies-in-entry-application) – Mark Seemann Apr 28 '16 at 06:58

1 Answers1

1

In App_start register web project specific dependencies (controllers, etc). Have a static method in BL layer which registers unit of work, repositories, etc. Call this static method in App_start when all the web dependencies are being registered as below:

//App_Start (web project)
var builder = new ContainerBuilder();
var config = GlobalConfiguration.Configuration;
MyProject.BusinessLayer.RegisterDependancies.Register(builder); <-- Register Unit of Work here in static BL method
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterApiControllers(typeof(MvcApplication).Assembly);
builder.RegisterModule<AutofacWebTypesModule>();
builder.RegisterWebApiFilterProvider(config);
builder.RegisterModule(new AutofacModules.AutoMapperModule());
builder.RegisterModule(new AutofacModules.Log4NetModule());

var container = builder.Build();

DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);


//Static method in BL
namespace MyProject.BusinessLayer
{
    public static class RegisterDependancies
    {
        public static void Register(ContainerBuilder builder)
        {
            builder.RegisterType<MyContext>().As<IDataContextAsync>().InstancePerLifetimeScope();
            builder.RegisterType<UnitOfWork>().As<IUnitOfWorkAsync>().InstancePerLifetimeScope();
            builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepositoryAsync<>)).InstancePerLifetimeScope();
            builder.RegisterAssemblyTypes(typeof(BusinessService).Assembly).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces().InstancePerLifetimeScope();
        }
    }
}
garethb
  • 3,951
  • 6
  • 32
  • 52
  • you are an absolute legend :) – Immortal Apr 26 '16 at 12:42
  • @immortal this what you want but this is killing IoC logic at all. – Erkan Demirel Apr 27 '16 at 05:13
  • @ErkanDemirel I do not have a better way for now. unless if you can suggest. – Immortal Apr 27 '16 at 10:38
  • @ErkanDemirel Why is this killing IoC? The same container is being passed to the static method so all lifetimes are handled by the same container, at least I thought but maybe I'm wrong? – garethb Apr 27 '16 at 22:13
  • @garethb You have one composition root, but it obeys Business Layer's rule so it's not rule maker. Also with this implemantation you make repository and business are coupled (Even they use interfaces). If you change implemantation on repository, driver project(web api) should know and you don't have to build/deploy/change anything else. But now if you change repository you should rebuild/deploy/change also business layer. In small projects you can't see drawback but in big projects or if projects get biggger this will make problem. – Erkan Demirel Apr 28 '16 at 06:43
  • If I understand this answer correctly, doesn't it mean that the business model now depends on the data access library? I'm guessing that `UnitOfWork` and `Repository` are implemented in the data access library, and I gather that the `RegisterDependancies` (sic!) method is defined in the business model. – Mark Seemann Apr 28 '16 at 07:05
  • @MarkSeemann ErkanDemirel How would you do this then? Move DI into a separate class? I still think keeping the UnitOfWork out of the web project warrants breaking a 'perfect' implementation. Especially when you have other programmers (lazy and junior) around... – garethb May 02 '16 at 23:24