温莎城堡,依赖注入 return null
Castle Windsor, dependency injections return null
可能我的想法一开始就错了
我有一个 MVC5 项目,我想在我的网站和 EF 之间实现一个存储库层(简单来说,这是一个学习项目)。
我有一个 EF Code First 上下文和一个存储库 class:
public interface IRepository<TDbContext> : IDisposable where TDbContext : class, new()
public class Repository<TContext> : IRepository<TContext>, IDisposable where TContext : DbContext, new()
然后我在第二层实现了额外的功能:
public interface ILog<TLogContext> : IRepository<TLogContext> where TLogContext : class, new()
public class Logger<TContext> : Repository<TContext>, ILog<TContext> where TContext : LogContext, new()
海豚是为我的所有上下文使用通用存储库,并在我的网站(日志记录、帐户管理等)中为不同的 areas/scopes 创建单独的上下文和单独的 "second layers",所以如果需要,我可以使用不同的数据库实现。
这是温莎实现:
Installer.cs
:
public class Installer : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
// Controller
container.Register(
Classes.FromThisAssembly().BasedOn<IController>().LifestyleTransient());
// EF, Business
container.Register(
Component.For<IRepository<LogContext>>()
.ImplementedBy<Repository<LogContext>>()
.LifestylePerWebRequest()
);
container.Register(
Component.For<ILog<LogContext>>()
.ImplementedBy<Logger<LogContext>>()
.LifestylePerWebRequest()
);
}
}
ControllerFactory.cs
:
public class ControllerFactory : DefaultControllerFactory
{
private readonly IKernel kernel;
public ControllerFactory(IKernel kernel)
{
this.kernel = kernel;
}
public override void ReleaseController(IController controller)
{
kernel.ReleaseComponent(controller);
}
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);
}
}
在Global.asax
中:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
// Windsor
container = new WindsorContainer().Install(FromAssembly.This());
// ContainerFactory loading
ControllerBuilder.Current.SetControllerFactory(new ControllerFactory(container.Kernel));
}
BaseController.cs
:
public class BaseController : Controller
{
// Services
internal ILog<LogContext> Logger { get; set; }
public void Test()
{
var allEvents = Logger.All<Event>();
}
}
并且... Logger
为空。为什么?
Logger
属性 需要 public
.
完整文档here,相关详情为:
Property injection of dependencies is designed to be done during component activation when a component is created. The responsibility of determining which properties are used for injection is fulfilled by default through PropertiesDependenciesModelInspector
- a IContributeComponentModelConstruction
implementation which uses all the following criteria to determine if a property represents a dependency:
- Has 'public' accessible setter
- Is an instance property
- If ComponentModel.InspectionBehavior is set to PropertiesInspectionBehavior.DeclaredOnly, is not inherited
- Does not have parameters
- Is not annotated with the Castle.Core.DoNotWireAttribute attribute
If a property meets all these criteria, a dependency model is created for it, and this is then resolved when the component dependencies are resolved during activation.
可能我的想法一开始就错了
我有一个 MVC5 项目,我想在我的网站和 EF 之间实现一个存储库层(简单来说,这是一个学习项目)。
我有一个 EF Code First 上下文和一个存储库 class:
public interface IRepository<TDbContext> : IDisposable where TDbContext : class, new()
public class Repository<TContext> : IRepository<TContext>, IDisposable where TContext : DbContext, new()
然后我在第二层实现了额外的功能:
public interface ILog<TLogContext> : IRepository<TLogContext> where TLogContext : class, new()
public class Logger<TContext> : Repository<TContext>, ILog<TContext> where TContext : LogContext, new()
海豚是为我的所有上下文使用通用存储库,并在我的网站(日志记录、帐户管理等)中为不同的 areas/scopes 创建单独的上下文和单独的 "second layers",所以如果需要,我可以使用不同的数据库实现。
这是温莎实现:
Installer.cs
:
public class Installer : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
// Controller
container.Register(
Classes.FromThisAssembly().BasedOn<IController>().LifestyleTransient());
// EF, Business
container.Register(
Component.For<IRepository<LogContext>>()
.ImplementedBy<Repository<LogContext>>()
.LifestylePerWebRequest()
);
container.Register(
Component.For<ILog<LogContext>>()
.ImplementedBy<Logger<LogContext>>()
.LifestylePerWebRequest()
);
}
}
ControllerFactory.cs
:
public class ControllerFactory : DefaultControllerFactory
{
private readonly IKernel kernel;
public ControllerFactory(IKernel kernel)
{
this.kernel = kernel;
}
public override void ReleaseController(IController controller)
{
kernel.ReleaseComponent(controller);
}
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);
}
}
在Global.asax
中:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
// Windsor
container = new WindsorContainer().Install(FromAssembly.This());
// ContainerFactory loading
ControllerBuilder.Current.SetControllerFactory(new ControllerFactory(container.Kernel));
}
BaseController.cs
:
public class BaseController : Controller
{
// Services
internal ILog<LogContext> Logger { get; set; }
public void Test()
{
var allEvents = Logger.All<Event>();
}
}
并且... Logger
为空。为什么?
Logger
属性 需要 public
.
完整文档here,相关详情为:
Property injection of dependencies is designed to be done during component activation when a component is created. The responsibility of determining which properties are used for injection is fulfilled by default through
PropertiesDependenciesModelInspector
- aIContributeComponentModelConstruction
implementation which uses all the following criteria to determine if a property represents a dependency:
- Has 'public' accessible setter
- Is an instance property
- If ComponentModel.InspectionBehavior is set to PropertiesInspectionBehavior.DeclaredOnly, is not inherited
- Does not have parameters
- Is not annotated with the Castle.Core.DoNotWireAttribute attribute
If a property meets all these criteria, a dependency model is created for it, and this is then resolved when the component dependencies are resolved during activation.