Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 外部违约与本地违约_Oop_Design Patterns_Dependency Injection_Anti Patterns - Fatal编程技术网

Oop 外部违约与本地违约

Oop 外部违约与本地违约,oop,design-patterns,dependency-injection,anti-patterns,Oop,Design Patterns,Dependency Injection,Anti Patterns,我正在读MarkSeemann的依赖注入书,我遇到了我不完全理解的混蛋注入反模式。我想得到一些关于如何区分外国违约和本地违约的指导。如果唯一的要求是外部默认值来自其他程序集 如果我有这样的设计(假设它是一个库类,所以我不允许使用IoC容器),该怎么办 名称空间文档阅读器 { 公共类DocumentReader:ISmartDocumentReader { 私有只读ISet文档阅读器; 公共文档阅读器(ISet文档阅读器) { this.documentReaders=documentReader

我正在读MarkSeemann的依赖注入书,我遇到了我不完全理解的混蛋注入反模式。我想得到一些关于如何区分外国违约和本地违约的指导。如果唯一的要求是外部默认值来自其他程序集

如果我有这样的设计(假设它是一个库类,所以我不允许使用IoC容器),该怎么办

名称空间文档阅读器
{
公共类DocumentReader:ISmartDocumentReader
{
私有只读ISet文档阅读器;
公共文档阅读器(ISet文档阅读器)
{
this.documentReaders=documentReaders;
}
公共文档阅读器()
:此(新哈希集(新IDocumentReader[]{new TxtReader(),new PdfReader(),new DocReader()}))
{
}
公共字符串读取(流、字符串文件类型)
{
var reader=documentReaders.SingleOrDefault(r=>r.SupportedFileType==fileType);
如果(读卡器==null)
抛出新ArgumentException(“不支持的文件类型”);
返回reader.Read(流,文件类型);
}
}
}
在阅读了书中的模式一章后,我怀疑这是否是正确的设计,目标是这个类将成为图书馆的公共API。所有特定的文档读取器(pdf、txt、doc)都在同一个程序集中,但它们是一些外部工具或库(如pdf box for pdfReader)的包装器


我觉得这个问题很有趣,但它并没有消除我所有的疑虑。如果有一天有人会添加新的文件阅读器呢。如果使用默认构造函数,则无法让文档阅读器知道新的特定阅读器。我是否应该删除默认构造函数并强制库用户使用IoC容器在应用程序的合成根连接(选择感兴趣的)依赖项?

最好删除默认构造函数,而是为消费者提供一个门面:从示例代码中挑出一些细节,您不需要
ISet
-您只需要
IEnumerable
,因此构造函数应该仅将其作为参数。这将使它更加灵活,因为更多的客户将能够使用它。@Mark Seemann:为什么IEnumerable会如此?有了ISet,我告诉我的图书馆用户,我只想要每种类型阅读器的一个副本,我在这里遗漏了什么?返回到本地默认问题:如果我的本地默认值与外部库/工具有一些依赖关系,它仍然被视为本地的吗?换句话说,这种关系是可传递的吗?在您的实现中,您只使用
IEnumerable
中的方法,那么为什么还需要其他方法呢?为什么只需要一个匹配的读卡器?如果将实现更改为使用FirstOrDefault,它将能够接受具有多个匹配读取器的序列,而不会引发异常-它甚至能够接受无限序列。Liskov替换原理和Postel定律都在这里起作用。对于另一个问题:是的,关系是传递的。如果不引用外部库就无法编译默认值,则默认值是外部默认值,而不是本地默认值。你可能会发现这个答案很有说明性:
namespace DocumentReader
{
public class DocumentReader : ISmartDocumentReader
{
    private readonly ISet<IDocumentReader> documentReaders;

    public DocumentReader(ISet<IDocumentReader> documentReaders)
    {
        this.documentReaders = documentReaders;
    }

    public DocumentReader()
        : this(new HashSet<IDocumentReader>(new IDocumentReader[] { new TxtReader(), new PdfReader(), new DocReader() }))
    {

    }

    public string Read(Stream stream, string fileType)
    {
        var reader = documentReaders.SingleOrDefault(r => r.SupportedFileType == fileType);
        if(reader == null)
            throw new ArgumentException("Not supported file type");

        return reader.Read(stream, fileType);
    }
}
}