2013-12-12 45 views
4

我有一个控制台应用程序,使用kernel.Get<SomeClass>();然而,SomeClass依赖于SomeDisposableClass。当SomeClass被垃圾收集时,如何设置我的绑定来处理SomeDisposableClass?我的MVC应用程序使用InRequestScope,这很好,但似乎并没有类似的控制台应用程序的范围。当SomeFunc完成到被布置Ninject瞬间范围与配置

public class SomeClass { 
    public SomeClass(SomeDisposableClass c) { 
     this.C = c; 
    } 

    private SomeDisposableClass C { get; set; } 

    // ... Business Methods ... // 
} 

我的模块

kernel.Bind<ISomeClass>().To<SomeClass>().In???Scope() 

我的控制台应用程序

public static void Main() { 
    SomeFunc(); 
    SomeFunc(); 
    Console.ReadLine(); 
} 

public static void SomeFunc() { 
    ISomeClass someClass = kernel.Get<ISomeClass>(); 
    // work 
} 

我想为SomeDisposableClass(或当:

实施例在这里垃圾收集器被调用)。但我不确定要使用哪个绑定范围。 InTransientScope不会调用dispose。难道我只是做SomeClass一次性和实施Dispose()和我的包裹在控制台应用程序的所有用法与using声明?

回答

7

在Ninject2,你可以这样做:

Bind<IService>().To<ServiceImpl>().InScope(ctx => ...); 

例如,用于InRequestScope()回调:

ctx => HttpContext.Current 

由于HttpContext.Current设置为HttpContext一个新实例网络上请求,只有服务的单个实例将每个请求被激活,并且当请求结束,HttpContext是(最终)收集后,实例将被停用。

您可以在控制台中使用静态变量来引用控制生命周期的对象。

public static object LifetimeController = new object(); 

可以将此作为您的寿命控制对象

Bind<IService>().To<ServiceImpl>().InScope(ctx => LifetimeController); 

而且每次要刷新的对象注册,你可以有这样的

public static void StartNewLifetime() 
{ 
    LifetimeController = new object(); 
} 

的方法请参见herehere有关更多信息,

+1

我upvoted,因为这是真棒......但我似乎无法到让它与测试一起工作。你需要'SomeClass'实现'IDisposable',你会不会?当你调用'StartNewLifetime()'时,Ninject应该在之前的'SomeClass'实例上调用'Dispose()'?无论如何,不​​是我的问题,所以我会放在一边,所以OP可能会作出判决... – McGarnagle

+0

@McGarnagle这里的细节:回调的对象也可以实现'INotifyWhenDisposed',一个Ninject接口,如果你希望确定性地停用“拥有”实例。如果作用域对象实现此接口,那么当它是Dispose()'d时,它所拥有的任何实例将立即停用。 – qujck

+3

我将此标记为答案。我最终做的是'绑定()。到().InScope(ctx => new object());'这给了我一个新的对象,每次仍然是GC ServiceImpl。我不得不等待垃圾收集,但是当我做了GC.Collect()时,它确实释放了依赖的一次性对象。 – Michael

1

使用InTransientScope - 那么Ninject容器将不会持有对该对象的任何引用。如果SomeClassSomeFunc结束时超出范围,则将以此方式进行GC'd。所有你需要做的是有SomeDisposableClass实例其终结处置:

public class SomeClass : IDisposable { 
    ~SomeClass() { 
     if (this.C != null) this.C.Dispose(); 
    } 
} 

这里是我是如何测试:

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); 
     } 
    } 
} 
+0

这是我想到的另一种选择。我知道终结者会被调用。谢谢你。 – Michael