首页 > 解决方案 > 将包含数据的大对象传递到接口中

问题描述

语境

我有一个使用策略模式的抽象类。

public interface IReader
{
    HashSet<DataSheet> Read(string fullFilePath, HashSet<string> sheetNames, ref string errors);
}

public abstract class AbstractReader : IReader
{
    public virtual HashSet<DataSheet> Read(string fullFilePath, Hashset<string> sheetNames, ref string errors)

    protected virtual void InitializeRowColInfo(string filePath, string sheetName)

    //And some other methods
}

该方法读取,读取一个excel文件并通过其参数获取所需信息并输出信息以进行进一步处理。

战略

为了实现抽象阅读器,我创建了一个覆盖它的新类。例如,

对于遵循我的抽象类的格式化逻辑的文件,

public class ConcreteReader1 : AbstractStandardReader
{
}

对于不遵循我的抽象类的格式化逻辑的文件,

public class ConcreteReader2 : AbstractStandardReader
{
    protected override void InitializeRowColInfo(string filePath, string sheetName)
}

其中我将根据文件的格式需要重写该方法,而从抽象类中重用常用方法。而对象的创建方法是这样的:

public IReader GetReader(string reader){
    if (reader.toUpper().trim().Equals("CONCRETEREADER1"){
        return new ConcreteReader1();
    }
    //Continue else ifs for the other readers
}

问题:参数

但是,由于我为所有方法包含的参数的刚性性质,每当需要需要额外参数的文件格式时,我都无法重用我的代码。

为了解决这个问题,我可以创建一个要传递的对象,例如 documentInfo 对象:

public class DocumentInfo
{
    public string FullReadFilePath { get; set; }
    public HashSet<string> SheetNames { get; set; }
    public string Errors { get; set; }
}

public interface IReader
{
    HashSet<DataSheet> Read(DocumentInfo documentInfo);
}

这样,任何需要的额外参数都可以添加到这个对象中,而不会影响现有的具体阅读器,我可以摆脱 ref 字符串。

然而,

  1. 存在冗余问题,因为任何新添加到 DocumentInfo 对象的属性将始终未初始化并且对于不使用它们的阅读器无用(并且还会使代码混乱)。

  2. 此外,我所有的其他方法都将依赖于这个对象,因为它包含有关读取的所有信息(fullFilePath、sheetNames 等)

有没有更好的方法来解决这个问题?

标签: c#design-patternsinterfacestrategy-pattern

解决方案


我的理解是,您正在尝试在不重新考虑对象责任的情况下进行技术重构(S of SOLID 原则https://stackify.com/solid-design-principles/)。这导致试图将所有内容组合到一个类中。我看到您可以通过以下方式重组类:

  1. DocumentInfo - 描述文档结构的数据对象(如果它是策略的一部分,则可能包括 RowColInfo)
  2. IReader - 阅读界面
  3. 错误 - 错误类(可以保留数组或创建单独的类)
  4. InitializeRowColInfo - 不确定你是否需要它,这看起来像是特定阅读器实现的一部分
  5. AbstractReader - 你真的需要它吗?重新考虑将技术方法保留在不同的地方/班级
  6. 获取特定的阅读器实现超出了阅读器范围(如果您愿意,请保持相同)

总结一下,我想使用下面的结构

public class DocumentInfo
{
    public HashSet<string> SheetNames { get; set; }
    // potentially RowColInfo if it's part of your configuration
}

public interface IReader
{
    HashSet<DataSheet> Read(DocumentInfo docuInfo, ref string errors);
}

public class ConcreteReader: IReader
{
    public ConcreteReader(string filePath) {...};
    public HashSet<DataSheet> Read(DocumentInfo docuInfo, ref string errors) {...};
}

实际上,就是这样。


推荐阅读