this should easy explain, i'm not sure how implement solution di container (autofac).
i've got repository
public class clientrepository { public clientrepository(mycontext context) { } }
and unit-of-work
public class unitofwork { public unitofwork(mycontext context, clientrepository repository) { } }
the unit-of-work/repository pattern dictates datacontext unit-of-work instantiated should passed constructor of repository, way using same datacontext
in other words, autofac should should this...
mycontext context = new mycontext(); clientrepository clientrepository = new clientrepository(context); unitofwork unitofwork = new unitofwork(context, clientrepository);
how can tell autofac wire correctly?
in response cyril's comment using func>...
i have class "clientservice" needs 1 or more of these unitofworks. in example below, there should no dependency sharing across unit of works "add" , "delete" (unless i've registered dependency singleton). if don't use func>, e.g. separate scopes, how achieve separation?
public class clientservice { private readonly func<owned<unitofwork>> _unitofworkfactory; public clientservice(func<owned<unitofwork>> unitofworkfactory) { _unitofworkfactory = unitofworkfactory; } public addclients(clients c) { using(var uoc = _unitofworkfactory()) { } } public deleteclients(clients c) { using(var uoc = _unitofworkfactory()) { } } }
to make autofac want need:
- create container
- register modules need in container
- register types need in modules
- set dependencyresolver in global.asax.cs
- see usage example (mvc)
so
- creating container
public static class dependencycontainer { internal static icontainer container; public static icontainer createcontainer(assembly assembly) { var builder = new containerbuilder(); builder.registercontrollers(assembly); imodule[] modules = { //you don't have create lots of modules... //but better have different modules different application layers new datamodule( /*some params if need*/), new dataaccessmodule( ), //new businesslogicmodule(), //... }; foreach (var module in modules) { builder.registermodule(module); } return container; } }
2-3. implementing modules used in container , register types
datamodule:
internal class datamodule : module { protected override void load(containerbuilder builder) { //when specify instanceperrequest means (resolved via di) //is using same datacontext current request builder.registertype<mycontext>().as<mycontext>().instanceperrequest(); } }
dataaccessmodule:
internal class dataaccessmodule : module { protected override void load(containerbuilder builder) { builder.registertype<unitofwork>().as<unitofwork>().instanceperrequest(); builder.registertype<clientrepository>().as<clientrepository>().instanceperrequest(); //if using generic repository can register them in 1 line this: //builder.registergeneric(typeof(repository<>)).as(typeof(irepository<>)).instanceperrequest(); } }
set dependencyresolver in global.asax.cs
public class mvcapplication : httpapplication { protected void application_start() { //default application_start() content //... //using our di var container = dependencycontainer.createcontainer(typeof(mvcapplication).assembly); dependencyresolver.setresolver(new autofacdependencyresolver(container)); } }
usage example
public class mycontroller : controller { private readonly unitofwork _unitofwork; private readonly clientrepository _clientrepository; public mycontroller(unitofwork unitofwork, clientrepository clientrepository) { _unitofwork = unitofwork; _clientrepository = clientrepository; } //when calling action dosomething, don't have worry constructor params (di pass them) public actionresult dosomething() { _clientrepository.dosomething(); return partialview("dosomething"); } }
Comments
Post a Comment