Tôi đã chạy vào nhiều lần này, vì vậy muốn sử dụng một ví dụ thực tế và lấy ý tưởng về cách các nhà phát triển C# có kinh nghiệm xử lý việc này.Thiết kế lớp cho hệ thống phân cấp, nhưng không gọn gàng vì vậy
Tôi đang viết một trình bao bọc .NET xung quanh thư viện MediaInfo không được quản lý, tập hợp dữ liệu khác nhau về tệp phương tiện (phim, hình ảnh ...).
MediaInfo có nhiều chức năng, mỗi chức năng áp dụng cho các loại tệp khác nhau. Ví dụ: "PixelAspectRatio" áp dụng cho hình ảnh và video nhưng không áp dụng cho âm thanh, phụ đề hoặc video khác.
Một tập hợp các chức năng tôi muốn quấn dưới:
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
Như bạn có thể thấy, sự bắt đầu của một ánh xạ lớp không-quá-xấu sẽ là một lớp cho các chức năng cụ thể để mỗi loại luồng và một lớp cơ sở có chức năng chung cho tất cả các loại.
Sau đó, đường dẫn này ít rõ ràng hơn một chút. Có nhiều chức năng phổ biến cho các loại luồng {chung, video, âm thanh, văn bản và hình ảnh}. Được rồi, vì vậy tôi đoán tôi có thể tạo một lớp với tên có mùi như "GeneralVideoAudioTextImage" và một tên khác có tên GeneralVideoAudioText (kế thừa từ GeneralVideoAudioTextImage) cho chức năng phổ biến cho những thứ đó chứ không phải luồng "Hình ảnh". Điều này sẽ lúng túng theo nguyên tắc "là một" của phân cấp lớp, tôi đoán vậy.
Điều này đã không được tìm kiếm thanh lịch, nhưng sau đó có những trường hợp không thường xuyên như "Chiều rộng" không phù hợp với bất kỳ nhóm nào là sạch một tập hợp con của một nhóm khác. Những trường hợp đó có thể chỉ đơn giản là trùng lặp chức năng khi cần thiết - triển khai trong Video, Văn bản và Hình ảnh riêng lẻ, nhưng điều đó rõ ràng sẽ vi phạm DRY.
Cách tiếp cận đầu tiên phổ biến là MI, C# không hỗ trợ. Câu trả lời thông thường cho rằng dường như là "sử dụng MI với giao diện", nhưng tôi không thể tìm thấy hoàn toàn xem làm thế nào mà có thể làm theo DRY. Có lẽ thất bại của tôi.
Phân cấp lớp đã được thảo luận trên SO trước đây, vì có alternatives đến MI (phương pháp mở rộng, v.v.) nhưng không có giải pháp nào phù hợp. Ví dụ, các phương thức mở rộng có vẻ tốt hơn được sử dụng cho các lớp có nguồn mà bạn không thể chỉnh sửa, như lớp String và khó định vị hơn vì chúng không thực sự gắn với lớp, mặc dù chúng có thể hoạt động. Tôi chưa tìm thấy câu hỏi nào về tình huống như thế này, mặc dù đó có thể là sự thất bại trong việc sử dụng công cụ tìm kiếm của tôi.
Một ví dụ về một tính năng MediaInfo, bọc, có thể là:
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;
}
Câu hỏi của tôi là: Làm thế nào bạn đã xử lý tình huống như thế này, các hệ thống đó là loại-of-thứ bậc-nhưng-không-khá? Bạn đã tìm thấy một chiến lược hợp lý thanh lịch, hay chỉ chấp nhận rằng không phải mọi vấn đề đơn giản đều có một?
Nếu bạn không tìm thấy giải pháp nào tốt hơn, có thể codegen sử dụng CodeDOM hoặc Roslyn có thể hữu ích. – svick