Class design for system hierarchical but not neat

I came across this several times, so I would like to use a real example and get an idea of ​​how experienced C # developers deal with this.

I am writing a .NET wrapper around the unmanaged MediaInfo library , which collects various data about media files (movies, images ...).

MediaInfo has many features, each of which applies to different types of files. For example, "PixelAspectRatio" applies to images and videos, but not to audio, subtitles, or others.

A subset of the functionality that I would like to wrap is given below:

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

, , , , .

. , {, , , }. , , , "GeneralVideoAudioTextImage", GeneralVideoAudioText ( GeneralVideoAudioTextImage) , , "". , "" .

, , "", , . , - Video, Text Image , DRY.

MI, # . , , " MI ", , DRY. , .

SO, - 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;
}

: , , , ? , ?

+5
2

, , , , :

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.
}
+5

, , , , , . , .

, SO, - .

, , - , . OSS , . , , , "IGeneralVideoAudioTextImageMenuCommon" "IVideoAudioTextImageMenuCommon"; 4 5 , :

    ///<summary>Represents a single video stream.</summary>
    public sealed class VideoStream : Media, IGeneralVideoAudioTextImageMenuCommon,
    IGeneralVideoAudioTextMenuCommon, IVideoAudioTextImageMenuCommon,
    IVideoTextImageCommon, /* ...ad nauseum. */
    {
        // What would you even name these variables?
        GeneralVideoAudioTextImageMenuCommon gvatimCommon;
        GeneralVideoAudioTextMenuCommon gvatmCommon;
        VideoAudioTextImageMenuCommon vatimCommon;
        VideoTextImageCommon vticCommon;

        public VideoStream(MediaInfo mi, int id) {
        gvatimCommon = new GeneralVideoAudioTextImageMenuCommon(mi, id);
        gvatmCommon = new GeneralVideoAudioTextMenuCommon(mi, id);
        vatimCommon = new VideoAudioTextImageMenuCommon(mi, id);
        vticCommon = new VideoTextImageCommon(mi, id);
        // --- and more. There are so far at least 10 groupings. 10!
        /* more code */
    }

, , "". "" - " ", , , " " "MotorcycleCarTruckOrAirplane", , ?

, . : " ?" "", , , . , , , : .

, - , , , , , , "MultiStreamCommon", , #:

public class MultiStreamCommon : Media
{
    public MultiStreamCommon(MediaInfo mediaInfo, StreamKind kind, int id)
        : base(mediaInfo, id) {
            this.kind = kind;
    }

    #region AllStreamsCommon
    string _format;
    ///<summary>The format or container of this file or stream.</summary>
    ///<example>Windows Media, JPEG, MPEG-4.</example>
    public string format { /* implementation */ };

    string _title;
    ///<summary>The title of the movie, track, song, etc..</summary>
    public string title { /* implementation */ };

    /* more accessors */
    #endregion

    #region VideoAudioTextCommon
    /* Methods appropriate to this region. */
    #endregion
    // More regions, one for each grouping.
}

MultiStreamCommon :

public sealed class VideoStream : Media
{
    readonly MultiStreamCommon streamCommon;

    ///<summary>VideoStream constructor</summary>
    ///<param name="mediaInfo">A MediaInfo object.</param>
    ///<param name="id">The ID for this audio stream.</param>
    public VideoStream(MediaInfo mediaInfo, int id) : base(mediaInfo, id) {
        this.kind = StreamKind.Video;
        streamCommon = new MultiStreamCommon(mediaInfo, kind, id);
    }

    public string format { get { return streamCommon.format; } }
    public string title { get { return streamCommon.title; } }
    public string uniqueId { get { return streamCommon.uniqueId; } }
    /* ...One line for every media function relevant to this stream type */
}

, , , MultiStreamCommon. , #region , , . , MediaInfo? , . , .

, - . , , . : , .

, , , .

, , ( .NET), Google Code . , , , , ( , ).

0

All Articles