【问题标题】:Making a class available only to a single other class使一个类只对一个其他类可用
【发布时间】:2010-08-23 16:08:52
【问题描述】:

我有一个 C# 项目,我在其中使用备忘录/命令模式来实现撤消/重做功能。该应用程序是一个 WPF 应用程序,它使用 StructureMap for IOC,具有广泛的单元测试,并通过使用 RhinoMocks 的接口使用模拟。

在我的代码中,我有一个 Operation 类,它代表所有可撤消的操作,我还有一个 IRepositoryWriter 接口,通过该接口路由所有对数据库的写入。

我想知道执行只有Operation 及其派生类应该能够使用IRepositoryWriter的策略的最佳方法是什么。

实现这一点的明显方法是使IRepositoryWriter 成为Operation 的受保护的嵌套接口。

优点:只有Operation 和派生类可以访问IRepositoryWriter

缺点:不再可以与 StructureMap 或 Unit Tested 一起使用。

还有哪些其他解决方案?该政策不需要严格强制执行 - 只要给其他人在代码库上工作的提示就足够了。

【问题讨论】:

    标签: c# design-patterns


    【解决方案1】:

    您可以像这样将您的应用程序划分为多个库:

    Lib1
        UI code
    Lib2
        Operation and derived classes
    Lib3
        IRepositoryWriter and implementation
    

    只有Lib2 应该有对Lib3 的引用。您甚至可以使用InternalsVisibleToAttribute 来确保Lib3 的内部组件仅对Lib2 可见,并使IRepositoryWriter 和实现internal

    这样你仍然可以拥有你想要的所有单元测试。当然,没有什么可以阻止其他开发人员创建从 Lib1Lib3 的引用,但这更容易实施。

    【讨论】:

    • 谢谢,是的,我考虑过,而且效果很好。但是,我不愿意基于此将我的代码拆分为 3 个不同的库。对我来说,理想情况下,库应该描述功能而不是实现细节(我认为这是这样做的)。
    • 我不太同意。您的 IRepositoryWriter(以及实现和支持类)包含写入数据库的功能。我想你也有一些 IRepositoryReader 或其他数据读取代码?这也可能是 Lib3 的一部分,它将为您提供一个数据访问组件,即 i.m.o.是单独库的逻辑候选者。我同意将 Operation 和相关类分离到一个单独的库中更值得商榷,但考虑到您的要求,我认为这是有道理的。
    【解决方案2】:

    该政策不需要严格执行——只要给其他人在代码库上工作的提示就足够了

    /// <summary>
    ///    blah blah, what this interface is for
    /// </summary>
    /// <remarks>
    ///   This interface should only be implemented by inheritors of Operation.
    /// </remarks>
    public interface IRepositoryWriter{}
    

    只是为您说明明显的解决方案。 ;)

    【讨论】:

    • :) 谢谢 - 不用说我已经考虑过了。挑剔:并不是接口只能由 Operation 的继承者实现 - 而是接口上的方法只能由 Operation 的继承者调用
    【解决方案3】:

    如果将 IRepositoryWriter 替换为 RepositoryWriter 并带有一个将 Operation 作为参数的构造函数?

    【讨论】:

    • 在我问这个问题之前,像这样的东西是我的首选解决方案;)虽然您不需要替换 IRepositoryWriter - 您使 RepositoryWriter 成为该接口的具体实现,并使其需要 Operation 作为参数到它的构造函数。这样它仍然可以被嘲笑。
    【解决方案4】:

    在这种情况下可能有点矫枉过正,但如果您绝对必须遵守 DRY 原则,您可以编写一些脚本来仅更改需要接口的 .cs 文件 - 该脚本可以读取一个文件,该文件只是一个类列表允许实现接口。这样,您可以将接口嵌套在每个使用它的类中,包括单元测试,而无需任何知识重复。当然,缺点是你引入了一个全新的复杂程度。

    事后看来,可能弊大于利,因为您可以添加评论以警告其他开发人员您正在做什么,但至少它对您的问题有不同的看法。

    【讨论】:

    • 哇,是的,确实很重量级!和有趣的想法,但我想如果它是两者之间的选择,我宁愿选择 cmets :)
    【解决方案5】:

    internal 关键字将类的访问权限限制为单个程序集中的元素,即内部类在程序集之外不可见 - 将 Operation、Operation 子类和 IRepositoryWriter 放入单个程序集中自己来

    【讨论】:

    • 将哪些类设为内部?这如何与单元测试一起工作?
    • 您需要针对 Operation 类层次结构进行单元测试-您要求您也受到约束-真正的问题是您希望在何种程度上执行该策略-从技术上讲,我同意提供建议手段但避开绝对执法的回应——我的回应只是提供绝对执法的机制
    猜你喜欢
    • 1970-01-01
    • 2019-09-24
    • 2012-11-09
    • 2014-04-21
    • 2010-12-28
    • 1970-01-01
    • 2014-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多