imd*_*sen 3 asp.net-mvc castle-windsor
我有下面的代码,可以没有任何问题 MAUserController.cs
public class MAUserController : ApiController
{
ILogService loggerService;
IMAUserService _service;
public MAUserController(ILogService loggerService, IMAUserService Service)
{
this.loggerService = loggerService;
this._service = Service;
}
}
Run Code Online (Sandbox Code Playgroud)
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()
);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我使用普通的控制器而不是ApiController,那么它会给我一个错误 UserController.cs
public class UserController : Controller
{
ILogService loggerService;
IMAUserService _service;
public UserController(ILogService loggerService, IMAUserService Service)
{
this.loggerService = loggerService;
this._service = Service;
}
}
Run Code Online (Sandbox Code Playgroud)
这会产生错误:
没有为此对象定义的无参数构造函数
我使用CastleDI Windsor进行依赖注入.
我需要做任何事情或注册一些东西吗?
第一种方法
建议:谨慎使用,因为它可能会导致Castle Windsor的内存泄漏.
您必须创建一个控制器激活器,它应该实现该IControllerActivator接口,以便使用您的DI容器来创建控制器实例:
public class MyWindsorControllerActivator : IControllerActivator
{
public MyWindsorControllerActivator(IWindsorContainer container)
{
_container = container;
}
private IWindsorContainer _container;
public IController Create(RequestContext requestContext, Type controllerType)
{
return _container.Resolve(controllerType) as IController;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,将此类添加到您的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();
);
}
}
Run Code Online (Sandbox Code Playgroud)
另外,根据Windsor容器创建自己的依赖项解析器:
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>();
}
}
Run Code Online (Sandbox Code Playgroud)
然后,最后,Application_Start在Global.asax.cs 中的方法中注册依赖项解析器:
DependencyResolver.SetResolver(new MyWindsorDependencyResolver(windsorContainer));
Run Code Online (Sandbox Code Playgroud)
这样,当MVC需要控制器激活器通过它的依赖解析器时,它将获得我们的,它将使用我们的Windsor容器来创建具有所有依赖性的控制器.
为了避免使用内存泄漏IControllerActivator,最简单的解决方案是使用每个线程或每个Web请求的生活方式,而不是注册组件的默认(Singleton),transient和pooled.有关如何使用Castle Windsor Container避免内存泄漏的详细信息,请查看此链接.
第二种方法
然而,正如@PhilDegenhardt所指出的,更好更正确的方法是实现自定义控制器工厂,以便能够释放由Castle Windsor DI Container创建的控制器组件.在这里您可以找到一个示例(请参阅有关依赖注入的部分).
从该示例中可以看出,实现可能是:
的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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
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); // The important part: release the component
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
}
return (IController)_kernel.Resolve(controllerType);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1068 次 |
| 最近记录: |