Just started playing with ninject – and I can’t get past this issue. Consider this setup:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IDataTransaction>().To<DataTransaction>().InRequestScope();
kernel.Bind<IdbAnalytics>().To<dbAnalytics>().InRequestScope();
kernel.Bind<IdbMembership>().To<dbMembership>().InRequestScope();
kernel.Bind<IAnalyticsWork>().To<AnalyticsWork>().InRequestScope();
kernel.Bind<IMembershipWork>().To<MembershipWork>().InRequestScope();
kernel.Bind<ILog>().To<Log>().InRequestScope();
...
}
With Log being injected into the above classes:
public class AnalyticsWork : IAnalyticsWork, IDisposable
{
private readonly IdbAnalytics _Context;
private readonly ILog _Log;
public AnalyticsWork(IdbAnalytics Context, ILog Log)
{
_Context = Context;
_Log = Log;
_Log.Write(LogEntryType.DEBUG, "Object Created");
}
...
}
This issue is the Log object gets disposed of ahead of the other objects (AnalyticsWork / MembershipWork). Is there any way to set the order that items should be disposed of? Or is this setup flawed?
I do not use NInject, but it sounds to me that you are registering the Log concrete as shared or per web request (as per the
InRequestScopemight indicate, again I do apologize for not using NInject so I am not sure what that does).For all of the loggers I’ve used, NLog, Log4Net, MS’ Logging Application Block, etc – they all require
Transientregistration, notScoped, because they take the superclass that initiated them to write out in the log as the calling class.As far as dispose order, I don’t think you can control that with any IoC container because the object cannot be disposed in different orders if another class still has a reliance. I ran into the same issues when I first started with IoC Containers years ago and thought, “Yeah, I’ll register everything as scoped!” Hehe, that didn’t work out very well.
I would say your objects just need to be registered differently. Only scope the items you really need scoped, everything else as
transientsorsingletons. I usually follow the pattern of:If I not using a
unit-of-workpattern with myORM, I will typically register my ORM containers asScopedso they can track the object changes for the life of the request, and SaveChanges() latter (e.g. Entity Framework 4, or NHibernate’s Session, etc).