2013-08-01 76 views
6

Tôi đang trong quá trình tạo bản phát hành nhỏ mới của số toy project của tôi. Dự án này được phát hành trên NuGet và tương thích với .NET 4.0 trở lên. Một số tính năng mới mà tôi giới thiệu yêu cầu .NET 4.5 (người dùng có thể giải quyết IReadOnlyCollection<T>IReadOnlyList<T>, cả hai giao diện được giới thiệu trong .NET 4.5), nhưng tôi cần giữ cho dự án tương thích với .NET 4.0, vì không tất cả các nhà phát triển có thể dễ dàng chuyển sang khung công tác .NET mới nhất.Cách bật tính tương thích về phía trước trên thư viện .NET có thể tái sử dụng?

Vì vậy, vấn đề tôi đang gặp phải là cách giải quyết vấn đề 'tương thích về phía trước' này. Có hai giải pháp mà tôi đã nghĩ đến, nhưng cả hai đều không hấp dẫn lắm, vì vậy hy vọng mọi người có thể cho tôi một số ý tưởng hoặc hướng dẫn tại đây.

Dưới đây là hai giải pháp tôi đã đưa ra:

Giải pháp 1: Sử dụng #if chỉ thị biên dịch và xây dựng một DLL mỗi phiên bản .NET framework và xuất xưởng những phiên bản sử dụng các gói NuGet và tải về tại khu vực dự án. Mặt khác của phương pháp này là khi các nhà phát triển cập nhật dự án Visual Studio của họ từ .NET 4.0 lên .NET 4.5, họ không tự động lấy phiên bản .NET 4.5 (với .NET 4.5 tính năng cụ thể). Điều này vi phạm các Principle of least astonishment và sẽ để lại các nhà phát triển ngạc nhiên vì sao tính năng này không hoạt động, khi họ thử sử dụng tính năng này một vài tháng sau đó.

Giải pháp 2: Sử dụng một DLL duy nhất và loại phát ra khi đang thực hiện cả hai giao diện mới khi chúng tồn tại trong miền ứng dụng hiện tại. Điều này cho phép vận chuyển một DLL duy nhất cho người dùng và cho phép các tính năng khả dụng khi nhà phát triển chuyển đổi các phiên bản .NET framework trong dự án của họ. Điều này sẽ làm cho mọi thứ 'hoạt động'. Đây là hướng tôi đang hướng tới btw.

Vì tôi cần trả về loại cần triển khai giao diện, nên nhược điểm là loại đó phải được tạo khi chạy bằng cách sử dụng Reflection.Emit, ModuleBuilder, TypeBuilder và các loại tương tự. Đây là sự hỗn loạn khó chịu nghiêm trọng. Nhưng bên cạnh đó, vì kiểu này phải được tạo ra trong một assembly mới (ẩn danh), tôi phải làm cho một số kiểu nội bộ công khai (một kiểu nó cần phải kế thừa từ và một giao diện nó cần thực hiện). Làm cho các loại nội bộ đó gây ô nhiễm cho API của dự án và sẽ không cho phép tôi thực hiện các thay đổi đối với các loại đó.

Tôi tin rằng đây là những lựa chọn của tôi, nhưng tôi có thể thiếu điều gì đó hiển nhiên. Vì vậy, câu hỏi của tôi là, tôi thiếu một khả năng? Có cách nào để phá vỡ các vấn đề cho giải pháp 1 hoặc nó sẽ là tốt hơn để đi với gốc hardcore của thời gian chạy loại phát ra?

+1

json.net sử dụng giải pháp 1. –

+0

Tôi không nghĩ tùy chọn đầu tiên sẽ bay khi đối mặt với nguyên tắc: tại sao tôi mong đợi tham chiếu của bên thứ ba bị cưỡng hiếp như vậy? Tôi sẽ ngạc nhiên nếu họ đã làm! –

+0

Không chắc chắn nếu nó thực sự phù hợp ở đây hoặc nếu nó thậm chí có liên quan ở đây nhưng không chuyển hướng lắp ráp tấn công một số hợp âm? –

Trả lời

2

Bạn có nghĩ về một hội đồng tùy chỉnh khác với các mục còn thiếu trong đó không? Sau đó, bạn kiểm tra nếu một kiểu/phương thức tồn tại (chỉ tồn tại trong .net 4.5) và nếu có, bạn nạp assembly vào.

Bằng cách đó bạn có thể giữ nguyên các phương pháp và lớp học giống nhau làm tất cả những phát ra điên rồ đó (chưa kể đến cú đánh hoàn hảo bạn sẽ mất nếu bạn thấy mình làm điều đó nhiều).

+0

Vâng, đó thực sự là một ý tưởng thực sự tốt. Nhược điểm duy nhất của điều này là có một hội đồng thêm, nhưng tôi thậm chí có thể đặt hội đồng đó trong một tài nguyên (ác nụ cười). – Steven

+0

Tôi nghĩ rằng trong một nguồn tài nguyên có thể là một nơi an toàn hơn để đặt nó quá. – jbtule

+0

@jbtule, Mặc dù tải lắp ráp trong một nguồn tài nguyên sẽ tốt đẹp, nó là cực kỳ khó chịu để làm điều này, trong khi sử dụng hội đồng đã ký, bởi vì có một chu kỳ phụ thuộc giữa các hội đồng. Core phải được xây dựng trước khi lắp ráp mới này (vì nó phụ thuộc vào lõi), nhưng cốt lõi cần phải lưu trữ lắp ráp đó trong tài nguyên của nó. Bạn thấy vấn đề? – Steven

0

Tôi có một dự án được gọi là Dynamitey cho phép bạn tải một loại tại thời gian chạy và được gọi là phương pháp tĩnh và hàm tạo với DLR. Mà sẽ được ít lộn xộn hơn rất nhiều phản ánh hoặc phát ra mã để tải một api mà không nhất thiết phải có sẵn.

dynamic bigIntType = new DynamicObjects.LateType("System.Numerics.BigInteger, System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); 

if (bigIntType.IsAvailable) 
{ 

    var one = [email protected](1); 
    var two = [email protected](2); 

    Assert.IsFalse(one.IsEven); 
    Assert.AreEqual(true, two.IsEven); 

    var tParsed = bigIntType.Parse("4"); 

    Assert.AreEqual(true, tParsed.IsEven); 
} 

Tôi cũng có một dự án có tên ImpromptuInterface, mà sẽ phát ra loại proxy cho giao diện xung quanh đối tượng mà vịt callable trận đấu đó (cũng sử dụng DLR).

var targetType =Type.GetType("System.Collections.Generic.IReadOnlyList`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); 

var list = new List<string>{"lala", "la","lala"}; 
object readonlyList; 
if(targetType != null){ 
    readonlyList = Impromptu.DynamicActLike(list, targetType); 
} 
+0

Thú vị công cụ, nhưng đối với dự án của tôi, tôi không muốn phụ thuộc kéo bất kỳ thư viện bên ngoài. – Steven

+0

Vâng, tôi nghĩ rằng tải một hội từ một nguồn tài nguyên nhúng là một giải pháp tốt hơn trong trường hợp của bạn. – jbtule