- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我已经遇到过好几次了,所以想用一个真实的例子来了解更有经验的 C# 开发人员如何处理这个问题。
我正在围绕非托管 MediaInfo 编写一个 .NET 包装器库,它收集有关媒体文件(电影、图像...)的各种数据。
MediaInfo 有很多函数,每个函数适用于不同类型的文件。例如,“PixelAspectRatio”适用于图像和视频,但不适用于音频、字幕或其他。
下面是我想包装的部分功能:
General Video Audio Text Image Chapters Menu (Name of function)
x x x x x x x Format
x x x x x x x Title
x x x x x x x UniqueID
x x x x x x CodecID
x x x x x x CodecID/Hint
x x x x x Language
x x x x x Encoded_Date
x x x x x Encoded_Library
x x x x x InternetMediaType
x x x x x StreamSize
x x x x BitDepth
x x x x Compression_Mode
x x x x Compression_Ratio
x x x x x Delay
x x x x x Duration
x x x BitRate
x x x BitRate_Mode
x x x ChannelLayout
x x x FrameCount
x x x FrameRate
x x x MuxingMode
x x x MuxingMode
x x x Source_Duration
x x x Height
x x x Width
x x PixelAspectRatio
x SamplingRate
x Album
x AudioCount
x ChaptersCount
x EncodedBy
x Grouping
x ImageCount
x OverallBitRate
x OverallBitRate_Maximum
x OverallBitRate_Minimum
x OverallBitRate_Nominal
x TextCount
x VideoCount
如您所见,一个还算不错的类映射的开始将是一个用于特定于每种流类型的功能的类和一个具有所有类型通用功能的基类。
然后这条路变得不那么明显了。 {general, video, audio, text, and image} 流类型有很多共同的功能。好吧,所以我想我可以创建一个名字像“GeneralVideoAudioTextImage”这样难闻的类,然后再创建一个名为 GeneralVideoAudioText(继承自 GeneralVideoAudioTextImage)的类,以实现这些东西共有的功能,但不是“图像”流。我猜这会尴尬地遵循类层次结构的“is a”规则。
这看起来已经不优雅了,但是偶尔会有像“宽度”这样的情况,它不适合任何组,而这些组完全是另一个组的子集。这些情况可以在必要时简单地复制功能——分别在视频、文本和图像中实现,但这显然违反了DRY。 .
常见的第一种方法是 MI,C# 不支持它。通常的答案似乎是“将 MI 与接口(interface)一起使用”,但我无法完全了解如何遵循 DRY。也许是我的失败。
之前已经在 SO 上讨论过类层次结构,alternatives 也是如此。到 MI(扩展方法等),但这些解决方案似乎都不合适。例如,扩展方法似乎更适用于其源代码无法编辑的类,如 String 类,并且更难定位,因为它们并不真正与类相关联,尽管它们可能有效。我还没有找到关于这种情况的问题,尽管这可能是我使用搜索工具的失败。
包装的 MediaInfo 功能示例可能是:
int _width = int.MinValue;
/// <summary>Width in pixels.</summary>
public int width {
get {
if(_width == int.MinValue)
_width = miGetInt("Width");
return _width;
}
}
// ... (Elsewhere, in another file) ...
/// <summary>Returns a MediaInfo value as an int, 0 if error.</summary>
/// <param name="parameter">The MediaInfo parameter.</param>
public int miGetInt(string parameter) {
int parsedValue;
string miResult = mediaInfo.Get(streamKind, id, parameter);
int.TryParse(miResult, out parsedValue);
return parsedValue;
}
我的问题是:您是如何处理这种情况的,系统是一种分层但不完全的系统?您是否找到了一个相当优雅的策略,或者只是承认并非每个简单问题都有一个策略?
最佳答案
我认为你最好使用接口(interface)的组合,如果实现比一堆属性更复杂,组合以提供接口(interface)的共享实现:
abstract class Media {
// General properties/functions
}
class VideoAndImageCommon { // Crappy name but you get the idea
// Functions used by both video and images
}
interface IVideoAndImageCommon {
// Common Video & Image interface
}
class Video : Media, IVideoAndImageCommon {
private readonly VideoAndImageCommon _commonImpl = new VideoAndImageCommon();
// Implementation of IVideoAndImageCommon delegates to _commonImpl.
}
class Image : Media, IVideoAndImageCommon {
private readonly VideoAndImageCommon _commonImpl = new VideoAndImageCommon();
// Implementation of IVideoAndImageCommon delegates to _commonImpl.
}
关于c# - 分层但不整齐的系统的类设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9730070/
我是一名优秀的程序员,十分优秀!