与相关课程紧密耦合?

sir*_*ide 5 .net c# oop design-patterns

我有定制的向导系统,到目前为止一直很合适.对于大多数向导,页面可以以相当通用的方式构造,因此只有一个类实现这些类型的页面.但是,有些需要自定义设计,因此这些类型的页面有一个抽象基类.由于VS设计器存在一些缺陷,页面本身不能是UI控件,也不是具有通用参数的抽象类(存在用于流畅编程的那些).因此,我遵循的一个选项是跨两个类实现页面,一个用于UI(源自UserControl并且可以设计),一个用于页面.该页面包含UI控件的一个实例,并将其嵌入其中以供显示.不是最佳的,但它的工作原理.

现在,这个设置出现了一个问题:UI控件类和页面类之间存在紧密耦合.这通常不会是一个大问题,除了可以从页面创建页面的专用版本.因此派生的控件和页面类也与它们紧密耦合.所以当我有控件和页面类的成员变量,属性和方法分别为控件或页面类型键入时(即控件类将具有属性)Page它指向控件嵌入的页面),我们遇到派生类的一个大问题.每个派生类必须以某种方式更改这些成员的类型.我曾经想过要做的是包括一个泛型类型参数,允许这些成员通常输入:

public class BaseControl<TControl, TPage>
    where TPage : BasePage<TPage, TControl>
    where TControl : BaseControl<TControl, TPage> {
    public TPage Page { get { ... } set { ... } }
    ...
}

public class BasePage<TPage, TControl>
    where TPage : BasePage<TPage, TControl>
    where TControl : BaseControl<TControl, TPage> {
    public TControl Control { get { ... } set { ... }
    ...
}

public class DerivedControl<TControl, TPage> : BaseControl<TControl, TPage>
    where TControl : DerivedControl<TControl, TPage>
    where TPage : DerivedPage<TPage, TControl> { }

public class DerivedPage<TPage, TControl> : BasePage<TPage, TControl>
    where TControl : DerivedControl<TControl, TPage>
    where TPage : DerivedPage<TPage, TControl> { }
Run Code Online (Sandbox Code Playgroud)

显然,这是我想要避免的那种C++风格的垃圾.除了丑陋之外,它还会产生一个实际问题,其中必须创建密封的"叶子"类来解决CRTP给我们带来的无限递归问题.

然而,替代方案也没有吸引力.我可以让那些成员具有固定类型的基本类型并在任何地方进行投射.这不会强制类型安全,它需要无意义的强制转换(我已经知道类型将是这样的,但编译器不会这样).我可以把它吸收并将页面和控件类合并为一个,没有abstract或泛型类型参数.这破坏了一口流利的编程系统,或使它更难实现,其中大部分重复(如果需要的话我会解释,但让我们姑且认为我设计的一部分是合法的).

因此,我对如何以理智的方式做到这一点有点不知所措.我到目前为止所考虑的一切都可以使用,但代码味道很糟糕.有什么我想念的东西,到目前为止这样做的一些方法让我望而却步?

Jon*_*eet 3

我的 Protocol Buffers port中有非常相似的代码,其中消息类型和该消息类型的构建器耦合在一起。

基本上,您试图表达一种 C# 泛型使之尴尬的关系。

就我而言,大部分内容都隐藏在生成的代码中,因此开发人员实际上不需要做太多事情......但它仍然很丑陋。我确实寻找过替代方案,但没有找到。我认为你所拥有的很可能是你能得到的最好的,恐怕......假设你写的关于 VS 约束的内容和你的其他要求是正确的。如果您发现自己能够使用非常不同的设计,那就太好了 - 但如果您需要两种相关的类型,我认为所有这些“垃圾”都是必需的:(