Reputation: 360
Probably my idea is wrong from the beginning.
I have an MVC5 project, and I'm tring to implement a repository layer between my website and EF (for semplicity, it's a learning project).
I have an EF Code First Context, and a Repository class:
public interface IRepository<TDbContext> : IDisposable where TDbContext : class, new()
public class Repository<TContext> : IRepository<TContext>, IDisposable where TContext : DbContext, new()
Then I have a second layer where I implement additional functions:
public interface ILog<TLogContext> : IRepository<TLogContext> where TLogContext : class, new()
public class Logger<TContext> : Repository<TContext>, ILog<TContext> where TContext : LogContext, new()
The porpouse is to use the generic repository for all my contexts, and to create separate contexts and separate "second layers" for different areas/scopes inside my website (Logging, Account Management, etc), so I can use, if I want, different DB implementations.
And this is the Windsor implementation:
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);
}
}
And in 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>();
}
}
And... Logger
is null. Why?
Upvotes: 1
Views: 1188
Reputation: 14580
The Logger
property needs to be public
.
Full documentation here, the relevant detail is:
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.
Upvotes: 3