简化C#中的循环通用约束?

时间:2014-08-25 19:06:25

标签: c# .net generics

给出以下基类:

public abstract class PurchaseSystemControllerBase<TController, TViewModel> : IInitializable
    where TController : PurchaseSystemControllerBase<TController, TViewModel>
    where TViewModel : PurchaseSystemViewModelBase<TController, TViewModel> {

    protected TViewModel ViewModel { get; private set; }

    ...
}

public abstract class PurchaseSystemViewModelBase<TController, TViewModel> : ViewModelBase
    where TController : PurchaseSystemControllerBase<TController, TViewModel>
    where TViewModel : PurchaseSystemViewModelBase<TController, TViewModel> {

    protected TController Controller { get; private set; }

    ...
}

具体实施如下:

public sealed class PurchaseSystemController : PurchaseSystemControllerBase<PurchaseSystemController, PurchaseSystemViewModel> {
    ...
}

public sealed class PurchaseSystemViewModel : PurchaseSystemViewModelBase<PurchaseSystemController, PurchaseSystemViewModel> {
    ...
}

有没有办法简化这个以便可以进行以下操作?

public sealed class PurchaseSystemController : PurchaseSystemControllerBase<PurchaseSystemViewModel> {
    ...
}

public sealed class PurchaseSystemViewModel : PurchaseSystemViewModelBase<PurchaseSystemController> {
    ...
}

2 个答案:

答案 0 :(得分:3)

不,不幸的是 - 至少,不是我意识到的,并没有失去某种类型的安全性。 我在my Protocol Buffers port中有一个非常类似的设置,在消息类型和相应的构建器类型之间。

如果您对使用一些非泛型基类型声明ViewModelController属性感到高兴,那就没问题 - 但如果您需要两者完全了解相应的类型,那么因为这种混乱而离开了。

(您可能需要考虑ViewModel和Controller 是否彼此都知道,请注意。)

答案 1 :(得分:1)

不,在保持您拥有的完全强类型的同时,这是不可能的。以下是如何将其缩减为更基本的输入的示例:

public abstract class PurchaseSystemControllerBase : IInitializable {
    protected PurchaseSystemViewModelBase ViewModel { get; private set; }
}
public abstract class PurchaseSystemControllerBase<TViewModel>
                    : PurchaseSystemControllerBase
    where TViewModel : PurchaseSystemViewModelBase {
    // note: property implementations should prevent this and base.ViewModel
    // from getting out of sync
    protected new TViewModel ViewModel { get; private set; }
}

public abstract class PurchaseSystemViewModelBase : ViewModelBase {
    protected PurchaseSystemControllerBase Controller { get; private set; }
}
public abstract class PurchaseSystemViewModelBase<TController>
                    : PurchaseSystemViewModelBase
    where TController : PurchaseSystemControllerBase {
    // note: property implementations should prevent this and base.Controller
    // from getting out of sync
    protected new TController Controller { get; private set; }
}


public sealed class PurchaseSystemController
                  : PurchaseSystemControllerBase<PurchaseSystemViewModel> {
}
public sealed class PurchaseSystemViewModel
                  : PurchaseSystemViewModelBase<PurchaseSystemController> {
}

这可能就足够了,特别是考虑到这些是protected属性。