asp.net mvc - How to use Dependency Injection with a Controller -
i have below code work without issue mausercontroller.cs
public class mausercontroller : apicontroller { ilogservice loggerservice; imauserservice _service; public mausercontroller(ilogservice loggerservice, imauserservice service) { this.loggerservice = loggerservice; this._service = service; } }
dependencyinstaller.cs
public class dependencyinstaller : iwindsorinstaller { public void install(iwindsorcontainer container, iconfigurationstore store) { container.register( component.for<ilogservice>().implementedby<logservice>().lifestyle.perwebrequest, component.for<idatabasefactory>().implementedby<databasefactory>().lifestyle.perwebrequest, component.for<iunitofwork>().implementedby<unitofwork>().lifestyle.perwebrequest, alltypes.fromthisassembly().basedon<ihttpcontroller>().lifestyletransient(), alltypes.fromassemblynamed("isos.health.service").where(type => type.name.endswith("service")).withserviceallinterfaces().lifestyleperwebrequest(), alltypes.fromassemblynamed("isos.health.repository").where(type => type.name.endswith("repository")).withserviceallinterfaces().lifestyleperwebrequest() ); } }
if using normal controller instead apicontroller gives me error usercontroller.cs
public class usercontroller : controller { ilogservice loggerservice; imauserservice _service; public usercontroller(ilogservice loggerservice, imauserservice service) { this.loggerservice = loggerservice; this._service = service; } }
this give error:
no parameterless constructor defined object
i using castledi windsor dependency injection.
do need or register something?
first approach
advice: use caution, because may cause memory leaks castle windsor.
you have create controller activator, should implement icontrolleractivator
interface, in order use di container create controller instances:
public class mywindsorcontrolleractivator : icontrolleractivator { public mywindsorcontrolleractivator(iwindsorcontainer container) { _container = container; } private iwindsorcontainer _container; public icontroller create(requestcontext requestcontext, type controllertype) { return _container.resolve(controllertype) icontroller; } }
then, add class dependencyinstaller
:
public class dependencyinstaller : iwindsorinstaller { public void install(iwindsorcontainer container, iconfigurationstore store) { container.register( // current code... component.for<icontrolleractivator>() .implementedby<mywindsorcontrolleractivator>() .dependson(dependency.onvalue("container", container)) .lifestylesingleton(); ); } }
also, create own dependency resolver based on windsor container:
public class mywindsordependencyresolver : idependencyresolver { public mywindsordependencyresolver(iwindsorcontainer container) { _container = container; } private iwindsorcontainer _container; public object getservice(type servicetype) { return _container.resolve(servicetype); } public ienumerable<object> getservices(type servicetype) { return _container.resolveall(servicetype).cast<object>(); } }
then, finally, register dependency resolver in application_start
method in global.asax.cs:
dependencyresolver.setresolver(new mywindsordependencyresolver(windsorcontainer));
this way, when mvc requires controller activator through it's dependency resolver, ours, use our windsor container create controllers it's dependencies.
in order avoid memory leaks using icontrolleractivator
, easiest solution use lifestyles per thread or per web request, rather default (singleton), transient , pooled, registered components. check this link more info how avoid memory leaks using castle windsor container.
second approach
however, pointed out @phildegenhardt, better , correct approach implement custom controller factory, in order able release controller component created castle windsor di container. here can find example (see section dependency injection).
taken example, implementation be:
global.asax.cs:
public class mvcapplication : system.web.httpapplication { private windsorcontainer _windsorcontainer; protected void application_start() { var _windsorcontainer = new windsorcontainer(); _windsorcontainer.install( new dependencyinstaller(), // other installers... ); controllerbuilder.current.setcontrollerfactory(new windsorcontrollerfactory(_windsorcontainer.kernel)); } protected void application_end() { if (_windsorcontainer != null) { _windsorcontainer.dispose(); } } }
windsorcontrollerfactory.cs:
public class windsorcontrollerfactory : defaultcontrollerfactory { private readonly ikernel _kernel; public windsorcontrollerfactory(ikernel kernel) { _kernel = kernel; } public override void releasecontroller(icontroller controller) { _kernel.releasecomponent(controller); // important part: release component } protected override icontroller getcontrollerinstance(requestcontext requestcontext, type controllertype) { if (controllertype == null) { throw new httpexception(404, string.format("the controller path '{0}' not found.", requestcontext.httpcontext.request.path)); } return (icontroller)_kernel.resolve(controllertype); } }
Comments
Post a Comment