C# NInject 3泄漏(有一个示例项目),是否可以强制移除对象?

C# NInject 3泄漏(有一个示例项目),是否可以强制移除对象?,c#,memory,scope,c#-3.0,ninject,C#,Memory,Scope,C# 3.0,Ninject,我创建了一个示例项目来模拟我在实际项目中面临的问题。 问题是,当我在一个周期内查询一些外部数据时(在现实生活中,我的项目查询窗口以查找匹配项,并在成功或超时过期时停止查询)。在我看来,NICATE不处理创建的对象,并将该循环视为一个长调用。 如何解决这种情况?也许,删掉填充列表的代码并将其放入另一个类中?或者简单地说,你能把我的示例项目做得更好吗 或其代码如下: public interface IMyObj : IDisposable { string Name { get; set;

我创建了一个示例项目来模拟我在实际项目中面临的问题。 问题是,当我在一个周期内查询一些外部数据时(在现实生活中,我的项目查询窗口以查找匹配项,并在成功或超时过期时停止查询)。在我看来,NICATE不处理创建的对象,并将该循环视为一个长调用。 如何解决这种情况?也许,删掉填充列表的代码并将其放入另一个类中?或者简单地说,你能把我的示例项目做得更好吗

或其代码如下:

public interface IMyObj : IDisposable
{
    string Name { get; set; }
}

public class MyObj : IMyObj
{
    public virtual string Name { get; set; }

    public virtual void Dispose()
    {
        Name = string.Empty;
        GC.SuppressFinalize(this);
    }
}

public class NjModule : NinjectModule
{
    public override void Load()
    {
        Bind<IMyObj>()
            .To<MyObj>()
            .InCallScope();

        Bind<Requester>()
            .ToSelf()
            .InSingletonScope();
    }
}

public class Requester
{
    public List<IMyObj> RequestObjects()
    {
        List<IMyObj> list = new List<IMyObj>();

        for(int i = 0; i < 10; i++) {
            var myObj = Program.Kernel.Get<IMyObj>();
            myObj.Name = "abcdefghijklmnopqrstuvwxyz";
            list.Add(myObj);
        }

        return list;
    }
}

class Program
{
    public static IKernel Kernel;

    public static void Main(string[] args)
    {
        Console.WriteLine("Hello NInject!");

        // TODO: Implement Functionality Here

        Kernel = new StandardKernel(new NjModule());
        Kernel.Settings.ActivationCacheDisabled = true;

        var requester = Kernel.Get<Requester>();

        for (int i = 0; i < 100000000; i++) {

            List<IMyObj> list =
                requester.RequestObjects();

            foreach (MyObj listItem in list) {
                listItem.Dispose();
            }
            list.Clear();
            list = null;

        }

        Console.Write("Press any key to continue . . . ");
        Console.ReadKey(true);
    }
}
公共接口IMyObj:IDisposable
{
字符串名称{get;set;}
}
公共类MyObj:IMyObj
{
公共虚拟字符串名称{get;set;}
公共虚拟void Dispose()
{
Name=string.Empty;
总干事(本);
}
}
公共类模块:Ninject模块
{
公共覆盖无效负载()
{
绑定()
.至()
.InCallScope();
绑定()
.ToSelf()
.InSingletonScope();
}
}
公共类请求者
{
公共列表请求对象()
{
列表=新列表();
对于(int i=0;i<10;i++){
var myObj=Program.Kernel.Get();
myObj.Name=“abcdefghijklmnopqrstuvxyz”;
添加列表(myObj);
}
退货清单;
}
}
班级计划
{
公共静态IKernel内核;
公共静态void Main(字符串[]args)
{
Console.WriteLine(“你好,NInject!”);
//TODO:在此处实现功能
内核=新的标准内核(new NjModule());
Kernel.Settings.ActivationCacheDisabled=true;
var requester=Kernel.Get();
对于(int i=0;i<100000000;i++){
列表=
requester.RequestObjects();
foreach(列表中的MyObj listItem){
Dispose();
}
list.Clear();
列表=空;
}
控制台。写入(“按任意键继续…”);
Console.ReadKey(true);
}
}

我通过使用ChildKernel修复了内存问题。目前,我不能说任何关于性能的问题,但是内存泄漏肯定已经修复:该项目从10MB开始,使用15-25MB。 不管怎样,我很乐意考虑其他解决方案。 我的解决方案如下():

public interface IMyObj : IDisposable
{
    string Name { get; set; }
}

public class MyObj : IMyObj
{
    public virtual string Name { get; set; }

    public virtual void Dispose()
    {
        Name = string.Empty;
        GC.SuppressFinalize(this);
    }
}

public class NjModule : NinjectModule
{
    public override void Load()
    {
        Bind<Requester>()
            .ToSelf()
            .InSingletonScope();

        Bind<IChildKernel>().ToSelf().InSingletonScope();
    }
}

public class NjChildKernelModule : NinjectModule
{
    public override void Load()
    {
        Bind<IMyObj>()
            .To<MyObj>()
            .InCallScope();
    }
}

public class Requester
{
    public List<IMyObj> RequestObjects(IChildKernel childKernel)
    {
        List<IMyObj> list = new List<IMyObj>();

        for(int i = 0; i < 10; i++) {
            var myObj = childKernel.Get<IMyObj>();
            myObj.Name = "abcdefghijklmnopqrstuvwxyz";
            list.Add(myObj);
        }

        return list;
    }
}

class Program
{
    public static IKernel Kernel;

    public static void Main(string[] args)
    {
        Console.WriteLine("Hello NInject!");

        // TODO: Implement Functionality Here

        Kernel = new StandardKernel(new NjModule());
        Kernel.Settings.ActivationCacheDisabled = true;

        var requester = Kernel.Get<Requester>();

        for (int i = 0; i < 100000000; i++) {

            var childKernel = new ChildKernel(Kernel, new NjChildKernelModule());
            childKernel.Settings.ActivationCacheDisabled = true;

            List<IMyObj> list =
                requester.RequestObjects(childKernel);

            foreach (MyObj listItem in list) {
                listItem.Dispose();
            }
            list.Clear();
            list = null;

            childKernel.Dispose();
        }

        Console.Write("Press any key to continue . . . ");
        Console.ReadKey(true);
    }
}
公共接口IMyObj:IDisposable
{
字符串名称{get;set;}
}
公共类MyObj:IMyObj
{
公共虚拟字符串名称{get;set;}
公共虚拟void Dispose()
{
Name=string.Empty;
总干事(本);
}
}
公共类模块:Ninject模块
{
公共覆盖无效负载()
{
绑定()
.ToSelf()
.InSingletonScope();
Bind().ToSelf().InSingletonScope();
}
}
公共类NjChildKernelModule:NinjectModule
{
公共覆盖无效负载()
{
绑定()
.至()
.InCallScope();
}
}
公共类请求者
{
公共列表请求对象(IChildKernel childKernel)
{
列表=新列表();
对于(int i=0;i<10;i++){
var myObj=childKernel.Get();
myObj.Name=“abcdefghijklmnopqrstuvxyz”;
添加列表(myObj);
}
退货清单;
}
}
班级计划
{
公共静态IKernel内核;
公共静态void Main(字符串[]args)
{
Console.WriteLine(“你好,NInject!”);
//TODO:在此处实现功能
内核=新的标准内核(new NjModule());
Kernel.Settings.ActivationCacheDisabled=true;
var requester=Kernel.Get();
对于(int i=0;i<100000000;i++){
var childKernel=new childKernel(Kernel,new NjChildKernelModule());
childKernel.Settings.ActivationCacheDisabled=true;
列表=
requester.RequestObjects(childKernel);
foreach(列表中的MyObj listItem){
Dispose();
}
list.Clear();
列表=空;
Dispose();
}
控制台。写入(“按任意键继续…”);
Console.ReadKey(true);
}
}

如果您认为这里存在误解。 我认为InCallScope的
没有做你认为应该做的事情。查看以下AllScope中
的集成测试:

this.kernel.Bind<Parent>().ToSelf();
this.kernel.Bind<Child>().ToSelf().InCallScope();
this.kernel.Bind<IGrandChild>().To<GrandChild>().InCallScope();

var parent1 = this.kernel.Get<Parent>();
var parent2 = this.kernel.Get<Parent>();
parent1.Dispose();

parent1.FirstChild.Should().BeSameAs(parent1.SecondChild);
parent1.GrandChild.Should().BeSameAs(parent1.FirstChild.GrandChild);
parent1.FirstChild.Should().NotBeSameAs(parent2.FirstChild);
parent1.GrandChild.Should().NotBeSameAs(parent2.GrandChild);

parent1.FirstChild.IsDisposed.Should().BeTrue();
parent1.FirstChild.GrandChild.IsDisposed.Should().BeTrue();
parent2.FirstChild.IsDisposed.Should().BeFalse();
parent2.FirstChild.GrandChild.IsDisposed.Should().BeFalse();

parent2.Dispose();
parent2.FirstChild.IsDisposed.Should().BeTrue();
parent2.FirstChild.GrandChild.IsDisposed.Should().BeTrue();
this.kernel.Bind().ToSelf();
this.kernel.Bind().ToSelf().InCallScope();
this.kernel.Bind().To().InCallScope();
var parent1=this.kernel.Get();
var parent2=this.kernel.Get();
parent1.Dispose();
parent1.FirstChild.Should().BeSameAs(parent1.SecondChild);
parent1.grander.Should().BeSameAs(parent1.FirstChild.grander);
parent1.FirstChild.Should().NotBeSameAs(parent2.FirstChild);
parent1.green.Should().NotBeSameAs(parent2.green);
parent1.FirstChild.IsDisposed.Should().BeTrue();
parent1.FirstChild.孙子.IsDisposed.Should().BeTrue();
parent2.FirstChild.IsDisposed.Should().BeFalse();
parent2.FirstChild.grant.IsDisposed.Should().BeFalse();
parent2.Dispose();
parent2.FirstChild.IsDisposed.Should().BeTrue();
parent2.FirstChild.孙子.IsDisposed.Should().BeTrue();
(来源:)

如您所见,
IChild
Parent
的范围内实例化<一旦父级
被释放,code>IChild
就会被释放

在您的示例中,
Requester
绑定到
InSingletonScope
。只有在处置了请求者
之后,才会处置其在ILDScope
中为请求者实例化的所有内容。 然而,由于您似乎没有在原始
请求者中使用ContextPreservation,因此实际上您的
IMyObj
甚至没有范围

您希望它如何工作?

最后