具有处理的Ninject瞬态范围

时间:2013-12-12 16:26:49

标签: c# dependency-injection scope ninject

我有一个使用kernel.Get<SomeClass>();的控制台应用程序但是,SomeClass依赖于SomeDisposableClass。当SomeDisposableClass被垃圾收集时,如何设置绑定以处置SomeClass?我的MVC应用程序使用InRequestScope并且效果很好,但似乎没有类似的控制台应用程序范围。

此处示例:

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完成时(或调用垃圾收集器时)处理SomeFunc。但我不确定使用哪种绑定范围。 InTransientScope永远不会召唤处置。我是否只需要SomeClass一次性并实现Dispose()并使用using声明将我的所有用法包装在控制台应用程序中?

2 个答案:

答案 0 :(得分:8)

在Ninject2中,您可以通过以下方式执行此操作:

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

例如,用于InRequestScope()的回调是:

ctx => HttpContext.Current

由于HttpContext.Current在每个Web请求上都设置为HttpContext的新实例,因此每个请求只会激活一个服务实例,并且当请求结束时{{1 (最终)收集,实例将被停用。

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

HttpContext

您可以将此注册为您的终身控制对象

public static object LifetimeController = new object();

每次要刷新对象时,都可以使用这样的方法

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

有关详细信息,请参阅herehere

答案 1 :(得分:0)

使用InTransientScope - 然后Ninject容器将不会保留对该对象的任何引用。这样SomeClass会在SomeFunc结束时超出范围时进行GC。您需要做的就是让它的终结器处理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);
        }
    }
}