使用C#中的接口层次结构建模系统

时间:2018-03-26 13:45:22

标签: c# oop generics inheritance interface

我试图在代码中模拟几个异构存储系统的容量利用率。

所有存储系统都有一些简单的概念,我试图从它们的具体实现中抽象出来。例如,所有系统都使用磁盘进行存储。可以将磁盘收集到一个组中,并将空间分配给这些组中的卷。某些系统具有特定的实现细节,这意味着它们的行为与其他系统不同。例如,几个系统具有不同类别的磁盘(例如快速,慢速),并且磁盘组属于一个类。有些系统只有一组没有相关磁盘类的磁盘。

我花了一些时间试图尽可能多地抽象出细节,并编写了一些接口来表示这些抽象。例如,IStorageContainer具有名称,描述,一些标志以显示容器是否支持各种存储技术,以及原始总大小。我的愿望是IStorageContainer可以代表一个磁盘,一组磁盘,一个磁盘类或一个卷。重要的是,IStorageContainer有一个父IStorageContainer和一些子IStorageContainer来表示磁盘组如何分成卷,而卷必须属于一组磁盘。

我已经构建了代表每个存储系统的类,每个存储系统都实现了IStorageContainer。我可以创建一个List<IStorageContainer>,添加不同派生类型的对象组合,但所有派生类型都实现IStorageContainer - 然后迭代列表以查找例如特定类型的对象。如果事先知道列表中对象的派生类型,我可以将它们从IStorageContainer转换回原始类型:

        foreach (var container in allContainers.SelectMany(
            container => container.Children.Where(
                child => child is System1Volume))
        .Cast<System1Volume>())
        {
            // Do stuff with System1Volume
            Console.WriteLine($"{container.Name}");
        }

但是,如果我有一个List<IStorageContainer>并且我事先不知道内容(即它们在运行时被“发现”),我想为每种类型显示不同的UI在列表中IStorageContainer,我不知道如何发现底层类型。使用大量“if”语句执行此操作似乎很麻烦。

        foreach
            (var container in allContainers.SelectMany
                (
                    container => container.Children
                )
            )
        {
            Console.WriteLine($"{container.Name} is a {container.GetType()}");
            if (container.GetType() == typeof(System1Volume))
            {
                // Show the System1DiskGroup UI
                var typedContainer = (System1Volume)container;
                Console.WriteLine(typedContainer.WordThatOnlySystem1VolumesKnow);
            }
            else if (container.GetType()==typeof(System2Volume))
            {
                // Show the System2DiskGroup UI
                var typedContainer = (System2Volume)container;
                Console.WriteLine(typedContainer.WordThatOnlySystem2VolumesKnow);
            }
        }

有更好的方法吗?

最后,假设System1Volume仅支持Children列表中的一组特定派生类型。我可以使用从IStorageContainer派生的接口作为约束来支持这个吗?

0 个答案:

没有答案