Dependency injection 温莎:如何处理使用基于接口的类型化工厂创建的对象
我开始使用Windsor,发现了这个非常非常酷的特性:类型化工厂。我了解到,每当我使用工厂获取一个实例时,我也必须要求它在我不需要的时候销毁该实例。我想知道这如何适用于一个非常常见的操作,例如打开磁盘上的文件。模型: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
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);
}