Dependency injection 温莎:如何处理使用基于接口的类型化工厂创建的对象

Dependency injection 温莎:如何处理使用基于接口的类型化工厂创建的对象,dependency-injection,inversion-of-control,castle-windsor,ioc-container,Dependency Injection,Inversion Of Control,Castle Windsor,Ioc Container,我开始使用Windsor,发现了这个非常非常酷的特性:类型化工厂。我了解到,每当我使用工厂获取一个实例时,我也必须要求它在我不需要的时候销毁该实例。我想知道这如何适用于一个非常常见的操作,例如打开磁盘上的文件。模型: interface IDisk IFile OpenFile(string path) interface IFileFactory IFile Create(string path) void Destroy(IFile openFile) interface IFi

我开始使用Windsor,发现了这个非常非常酷的特性:类型化工厂。我了解到,每当我使用工厂获取一个实例时,我也必须要求它在我不需要的时候销毁该实例。我想知道这如何适用于一个非常常见的操作,例如打开磁盘上的文件。模型:

interface IDisk
  IFile OpenFile(string path)
interface IFileFactory
  IFile Create(string path)
  void Destroy(IFile openFile)
interface IFile // empty, it's not important what it does

class Disk : IDisk
  ctor(IFileFactory fileFactory)
  IFile OpenFile(string path)
     return fileFactory.Create(path)
用户代码:

disk = container.Resolve<IDisk>() // disk is root so this is not SL
file = disk.OpenFile("foo.bar");
// do something with file
我也不喜欢这个。。。如果我更改模型,使文件不会自动关闭,但磁盘会关闭文件,则可以避免所有这些问题:

//file.Close() // not supported, by design
disk.Close(file)
这对于编写
磁盘
文件
类的我来说更容易,但我担心我的用户不会喜欢这种“新模式”


想法?

好的,让我按顺序说明:

一般.NET用户都会调用file.Dispose()

无论是否使用容器,调用
file.Dispose()
都是错误的。NET中的规则是,你不应该破坏你没有创造的东西

这适用于
.Dispose()
以及
ctor(Action destroyCallback)

那么谁拥有这个文件?就您的代码而言,工厂是这样做的。因此,工厂有责任在归档后进行清理

如果您将工厂作为
磁盘
的一个实现细节(您很可能应该这样做),那么
磁盘
是打开和关闭文件的表面积API,因此它需要一个
关闭(IFile文件)
方法,该方法作为实施细节传递给工厂

因此,文件的用法如下所示:

var myfile = disk.OpenFile(@"c:\myfile.txt);
try
{
   DoSomethingWithTheFile(myFile);
}
finally
{
   disk.Close(myFile);
}
[编辑:根据评论]

如果您希望并希望您的用户拥有一些
IDisposable
对象,那么就给他们一个(我宁愿建议不要这样做,但这不是我的要求)

然后,
OpenFile
方法将返回如下所示的对象:

public class FileScope:IDisposable
{
   private Action<IFile> close;

   public FileScope(IFile file, Action<IFile> close)
   {
      File = file;
      this.close = close;
   }


   public IFile File {get; private set;}

   public void Dispose()
   {
      close(file);
   }
}

我完全同意这一点。我所说的“一般.NET用户会调用file.Dispose()”是指在.NET中执行此操作的标准方法是使用(var file=file.OpenRead(“file”){…},在这种情况下,调用方拥有文件实例,并对其销毁负责。我担心的是,人们太习惯于自己打扫卫生,以至于常常忘记所有权规则。比如“好了,我已经处理完这个文件了,现在我只需要打电话给Dispose…但是等等,没有Dispose!”总之,他们必须处理这个问题,因为这个是管理员,先生!关于编辑:我不知道如何在
FileScope
中设置文件实例。setter是私有的,它也不会被注入到ctor中……它应该从创建它的
磁盘
传递到.ctor中。让我来修,谢谢!我将尝试
disk.Close(file)
,看看它是如何工作的。
FileScope
也是一个好主意,如果以后需要,可以很容易地切换到它。我不同意你的说法:“在.NET中,规则是你不应该破坏你没有创建的东西。”。我看到这种模式一直在使用。例如,nHibernate会话管理的认可模式是一个代码块,类似于使用(ISession session=sessionFactory.OpenSession()){…}
。看见
public class FileScope:IDisposable
{
   private Action<IFile> close;

   public FileScope(IFile file, Action<IFile> close)
   {
      File = file;
      this.close = close;
   }


   public IFile File {get; private set;}

   public void Dispose()
   {
      close(file);
   }
}
public FileScope OpenFile(string path)
{
   return new FileScope(fileFactory.Create(path),Close);
}