Reputation: 3272
I have a console app that uses kernel.Get<SomeClass>();
However, SomeClass
has a dependency on SomeDisposableClass
. How can I set up my binding to dispose of SomeDisposableClass
when SomeClass
is garbage collected? My MVC app uses InRequestScope
and that works great, but there doesn't seem to be an analogous scope for console apps.
Example here:
public class SomeClass {
public SomeClass(SomeDisposableClass c) {
this.C = c;
}
private SomeDisposableClass C { get; set; }
// ... Business Methods ... //
}
My module
kernel.Bind<ISomeClass>().To<SomeClass>().In???Scope()
My console app
public static void Main() {
SomeFunc();
SomeFunc();
Console.ReadLine();
}
public static void SomeFunc() {
ISomeClass someClass = kernel.Get<ISomeClass>();
// work
}
I'd like for SomeDisposableClass
to be disposed when SomeFunc
is finished (or when the garbage collector is called). But I'm not sure of which binding scope to use. InTransientScope
doesn't ever call dispose. Do I just have to make SomeClass
disposable and implement Dispose()
and wrap all my usages in the console app with a using
statement?
Upvotes: 7
Views: 9615
Reputation: 102743
Use InTransientScope
-- then the Ninject container will not hold any reference to the object. That way SomeClass
will be GC'd when it goes out of scope at the end of SomeFunc
. All you need to do is have its finalizer dispose of the SomeDisposableClass
instance:
public class SomeClass : IDisposable {
~SomeClass() {
if (this.C != null) this.C.Dispose();
}
}
Here's how I was testing:
class Program
{
private static IKernel _kernel;
static void Main(string[] args)
{
_kernel = new StandardKernel();
_kernel.Bind<ISomeClass>().To<SomeClass>().InTransientScope();
while (true)
{
LifetimeController = new object();
SomeFunc();
Thread.Sleep(10);
}
}
public static void SomeFunc()
{
_kernel.Get<ISomeClass>();
}
public interface ISomeClass { }
public class SomeClass : ISomeClass
{
public SomeDisposableClass C = new SomeDisposableClass();
~SomeClass()
{
Console.WriteLine("{0} finalized", this);
C.Dispose();
}
}
public class SomeDisposableClass : IDisposable
{
private byte[] bytes = new byte[1000000];
public void Dispose()
{
Console.WriteLine("{0} disposed", this);
}
}
}
Upvotes: -1
Reputation: 14580
In Ninject2, you can do this by:
Bind<IService>().To<ServiceImpl>().InScope(ctx => ...);
For example, the callback used for InRequestScope()
is:
ctx => HttpContext.Current
Since HttpContext.Current
is set to a new instance of HttpContext
on each web request, only a single instance of the service will be activated for each request, and when the request ends and the HttpContext
is (eventually) collected, the instances will be deactivated.
You can have a static variable within your console to reference an object that will control lifetime.
public static object LifetimeController = new object();
You can register this as your lifetime control object
Bind<IService>().To<ServiceImpl>().InScope(ctx => LifetimeController);
And each time you want to refresh the objects you can have a method like this
public static void StartNewLifetime()
{
LifetimeController = new object();
}
See here and here for more information
Upvotes: 11