C# NInject 3泄漏(有一个示例项目),是否可以强制移除对象?
我创建了一个示例项目来模拟我在实际项目中面临的问题。 问题是,当我在一个周期内查询一些外部数据时(在现实生活中,我的项目查询窗口以查找匹配项,并在成功或超时过期时停止查询)。在我看来,NICATE不处理创建的对象,并将该循环视为一个长调用。 如何解决这种情况?也许,删掉填充列表的代码并将其放入另一个类中?或者简单地说,你能把我的示例项目做得更好吗 或其代码如下: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;
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
甚至没有范围
您希望它如何工作?最后