Bạn có một câu hỏi hay. Có lẽ có một số đánh đổi với giải pháp của bạn. Câu trả lời cuối cùng thực sự phụ thuộc vào ý của bạn khi phụ thuộc vào nền tảng. Ví dụ: nếu bạn đang bắt đầu một quy trình để khởi động các ứng dụng bên ngoài và bạn chỉ cần chuyển đổi giữa ứng dụng này sang ứng dụng khác, bạn có thể có thể xử lý việc đó mà không gặp quá nhiều phức tạp. Nếu bạn đang nói P / Gọi với các thư viện riêng, thì sẽ còn một chút nữa phải làm. Tuy nhiên, nếu bạn đang liên kết với các thư viện chỉ tồn tại trên một nền tảng, có lẽ bạn sẽ cần phải sử dụng nhiều tập hợp.
Ứng dụng bên ngoài
Bạn có thể sẽ không cần phải sử dụng #if
báo cáo trong tình huống này. Chỉ cần thiết lập một số giao diện và có một triển khai trên mỗi nền tảng. Sử dụng một nhà máy để phát hiện nền tảng và cung cấp ví dụ phù hợp.
Trong một số trường hợp, nó chỉ là một tệp nhị phân được biên dịch cho một nền tảng cụ thể nhưng tên của tệp thực thi và tất cả các tham số được xác định giống nhau. Trong trường hợp đó, đó là vấn đề giải quyết quyền thực thi. Đối với một ứng dụng chuyển đổi âm thanh hàng loạt có thể chạy trên Windows và Linux, tôi đã có một trình khởi tạo tĩnh giải quyết tên nhị phân.
public class AudioProcessor
{
private static readonly string AppName = "lame";
private static readonly string FullAppPath;
static AudioProcessor()
{
var platform = DetectPlatform();
var architecture = Detect64or32Bits();
FullAppPath = Path.combine(platform, architecture, AppName);
}
}
Không có gì lạ mắt ở đây. Chỉ là những lớp học thời trang tốt.
P / Gọi
P / Gọi là một chút phức tạp hơn. Điểm mấu chốt là bạn cần đảm bảo tải đúng phiên bản của thư viện gốc. Trên cửa sổ, bạn sẽ P / Gọi SetDllDirectory()
. Các nền tảng khác nhau có thể không cần bước đó. Vì vậy, đây là nơi mọi thứ có thể trở nên lộn xộn. Bạn có thể cần sử dụng các #if
câu lệnh để kiểm soát cuộc gọi nào được sử dụng để kiểm soát việc giải quyết đường dẫn thư viện của bạn - đặc biệt nếu bạn đưa nó vào gói phân phối.
Liên kết đến các thư viện phụ thuộc nền tảng hoàn toàn khác nhau
Cách tiếp cận đa mục tiêu của trường học cũ có thể hữu ích ở đây. Tuy nhiên, nó đi kèm với rất nhiều xấu xí. Trong những ngày mà một số dự án cố gắng có cùng mục tiêu DLL Silverlight, WPF và có khả năng UAP, bạn sẽ phải biên dịch ứng dụng nhiều lần với các thẻ biên dịch khác nhau. Thách thức với mỗi nền tảng ở trên là trong khi chúng có chung các khái niệm, các nền tảng đủ khác nhau mà bạn phải làm việc xung quanh những khác biệt đó. Đây là nơi chúng ta nhận được vào địa ngục #if
.
Cách tiếp cận này cũng yêu cầu chỉnh sửa .csproj
tập tin để xử lý các tham chiếu phụ thuộc vào nền tảng. Vì .csproj
tệp của bạn là tệp MSBuild, nên hoàn toàn có thể thực hiện theo cách đã biết và có thể dự đoán được.
#if địa ngục
Bạn có thể bật và tắt các phần của mã bằng cách sử dụng các #if
câu lệnh để có hiệu quả trong việc xử lý các khác biệt nhỏ giữa các ứng dụng. Nhìn bề ngoài có vẻ như là một ý tưởng tốt. Tôi thậm chí đã sử dụng nó như một phương tiện để bật và tắt trực quan hóa hộp giới hạn để gỡ lỗi mã vẽ.
Vấn đề số 1 với #if
là không có mã nào bị tắt được đánh giá bởi trình phân tích cú pháp. Bạn có thể có lỗi cú pháp tiềm ẩn hoặc tệ hơn là lỗi logic đang chờ bạn biên dịch lại thư viện. Điều này càng trở nên rắc rối hơn với mã tái cấu trúc. Một cái gì đó đơn giản như đổi tên một phương thức hoặc thay đổi thứ tự các tham số thường sẽ được xử lý OK, nhưng vì trình phân tích cú pháp không bao giờ đánh giá bất cứ điều gì bị tắt bởi #if
câu lệnh mà bạn đột nhiên bị hỏng mã mà bạn sẽ không thấy cho đến khi bạn biên dịch lại.
Tất cả các mã gỡ lỗi của tôi được viết theo cách đó phải được viết lại sau khi một loạt các phép tái cấu trúc đã phá vỡ nó. Trong quá trình viết lại, tôi đã sử dụng một lớp cấu hình toàn cầu để bật và tắt các tính năng đó. Điều đó làm cho nó tái cấu trúc công cụ bằng chứng, nhưng một giải pháp như vậy không giúp ích gì khi API hoàn toàn khác.
Phương pháp ưa thích của tôi
Phương pháp ưa thích của tôi, dựa trên nhiều bài học đau đớn đã học và thậm chí dựa trên ví dụ của chính Microsoft, là sử dụng nhiều tổ hợp.
Tập hợp NetSt Chuẩn một lõi sẽ xác định tất cả các giao diện và chứa tất cả các mã chung. Việc triển khai phụ thuộc nền tảng sẽ nằm trong một hội đồng riêng biệt sẽ thêm các tính năng khi được bao gồm.
Cách tiếp cận này được minh họa bằng API cấu hình mới và kiến trúc Nhận dạng hiện tại. Khi bạn cần tích hợp cụ thể hơn, bạn chỉ cần thêm các cụm mới đó. Những hội đồng này cũng cung cấp các chức năng mở rộng để kết hợp chính nó vào thiết lập của bạn. Nếu bạn đang sử dụng phương pháp tiêm phụ thuộc, các phương thức mở rộng đó cho phép thư viện đăng ký các dịch vụ của nó.
Đây là cách duy nhất tôi biết để tránh #if
địa ngục và thỏa mãn một môi trường khác biệt đáng kể.