2013-05-04 52 views
7

Tôi cần phải thêm và/hoặc sửa đổi các cấu hình để cho phép nhiều lớp học và thành viên được chia sẻ trong PCL (nhiều trong số chúng được xây dựng trong khuôn khổ, chẳng hạn như Thread.Sleep). Cách tốt nhất để làm điều này là gì? Có công cụ nào để giúp điều đó không?



PS: Tôi không tìm kiếm một anwser cho tôi biết NO hoặc DỪNG. Tôi muốn có biên dịch-một lần DLL có thể được chia sẻ trong môi trường khác nhau. Không có nền tảng nhị phân, không biên dịch lại, không có ifdef.


Sau đây là những gì tôi có cho đến nay:

Tùy chỉnh Cấu hình Thư viện Lớp Di động .NET?

Yêu cầu:

  • Target environements: Silverlight 5 và .NET Framework 4.5.
  • Mục đích của PCLs: chia sẻ cơ sở hạ tầng của RIA client và máy chủ ASP.NET (không WCF)
  • Có gì thiếu trong các cấu hình mặc định: XPath, phương pháp đề, DynamicMethod/ILGenerator

hồ sơ PCL: dưới Reference Assemblies \ Microsoft \ Framework.NETPortable:

  • Tất cả hội đang cuống, với thuộc tính "Retargetable" thiết lập.
  • Tất cả hội có cờ = 0x171: 0x001 được ký kết, 0x100 là retargetable, và 0x070 là undefined trong AssemblyNameFlags (dường như không có hiệu lực)
  • Tất cả các tài liệu tham khảo giữa hội là với "Retargetable" thuộc tính là tốt.
  • Tất cả các hội đồng có hỗ trợ Silverlight được phiên bản 2.0.5.0.
  • Built binaries PCL chứa hai tài liệu tham khảo cho mỗi cụm gọi (ví dụ: mscorlib 2.0.5.0 retargetable + mscorlib 4,0)

Customization nỗ lựC# 1

  • hồ sơ: Silverlight 5 +. NET Framework 4.5 (hồ sơ 24)
  • Sao chép SL5 mscorlib.dll đến hồ sơ 24
  • Đánh dấu SL5 mscorlib.dll như retargetable (thay đổi để chậm trễ đã ký)
  • ReSharper: thất bại trong việc giải quyết tất cả các phương pháp khuyến nông, lỗi trong generic loại/giá trị trận đấu
  • tích xây dựng: thành công, Run: thành công

nỗ lực Customization # 2

  • hồ sơ: Silverlight 5 + Khuôn khổ .NET 4.5 (hồ sơ 24)
  • Sao chép tất cả các file DLL SL5 đến hồ sơ 24
  • Đánh dấu tất cả SL5 DLL như retargetable (thay đổi để chậm trễ đã ký)
  • Đánh dấu tất cả tài liệu tham khảo giữa SL5 DLL như retargetable
  • ReSharper: thất bại trong việc giải quyết tất cả các phương pháp khuyến nông, lỗi trong generic loại/giá trị trận đấu
  • tích xây dựng: thành công, Run: thành công

nỗ lực Customization # 3

  • hồ sơ: Silverlight 4 + .NET Framework 4.0.3 (hồ sơ 18)
  • Sao chép SL4 mscorlib.dll đến hồ sơ 18
  • Đánh dấu SL4 mscorlib.dll như retargetable (thay đổi để chậm trễ đã ký)
  • ReSharper: thành công
  • tích xây dựng: thành công, Run: thành công

nỗ lực Customization # 4

  • hồ sơ: Silverlight 4 + .NET Framework 4.0.3 (hồ sơ 18)
  • Sao chép tất cả SL4 DLL để cấu hình 18
  • Set phiên bản .NET runtime của tất cả các DLL SL4 để v4 (DLL gốc có mà, không rõ tác dụng)
  • Đánh dấu tất cả SL4 DLL như retargetable (thay đổi để chậm trễ đã ký)
  • Đánh dấu tất cả tài liệu tham khảo giữa SL4 DLL như retargetable
  • ReSharper: thành công
  • tích xây dựng: thành công, Run: thành công

nỗ lực Customization # 5 kế thừa # 4

  • hồ sơ: Silverlight 4 + .NET Framework 4.0.3 (hồ sơ 18)
  • Thêm System.Numerics SL4 của (bao gồm trong các cấu SL khác) để RedistList \ FrameworkList.xml
  • Thêm hệ thống SL4.Xml.XPath (không được bao gồm trong bất kỳ cấu hình SL nào) vào RedistList \ FrameworkList.xml
  • Kết quả: không thể giải quyết System.Numerics và System.Xml.XPath khỏi def ault PCL tham chiếu
  • Fixes: tài liệu tham khảo cả DLL bằng tay - không thể buộc họ phải được retargetable, mặc dù VS sẽ không biên dịch với System.Numerics phi retargetable hoặc System.Xml.XPath do cho vấn đề lưu ý dưới đây

Ghi chú:

  • Compile lỗi: "... theo quy định tại một hội đồng đó không được tham chiếu, Bạn phải thêm một tham chiếu đến lắp ráp".Xảy ra sau khi tất cả các hội đồng được thực hiện có thể nhắm mục tiêu lại, nhưng một trong các tham chiếu giữa chúng không bị thay đổi thành "có thể nhắm mục tiêu lại"

Nó hoạt động ở một mức độ nhất định, nhưng khá phiền hà khi tùy chỉnh các DLL được tham chiếu hiện tại hoặc thêm mới. xác nhận mã PCL sau khi ghi đè các DLL được tham chiếu (nếu có thể).

+2

Tôi biết bạn không * tìm kiếm * câu trả lời để cho bạn biết chỉ cần dừng lại, nhưng ý tưởng bạn chỉ có thể chọn và chọn những phần khung bạn muốn đưa vào và nó sẽ hoạt động, là thực sự không phải là một hợp lý. Ngay cả khi bạn tìm thấy một số cách vụng về của việc làm cho nó làm việc ở một mức độ nào đó, sớm hay muộn bạn sẽ trở thành unstuck - tại thời điểm đó bạn sẽ phải lãng phí rất nhiều thời gian. –

+0

Nhưng nó chỉ lúng túng nếu không có công cụ hỗ trợ thích hợp. Nếu có một công cụ để tạo ra các file DLL cho các tài liệu tham khảo, nó sẽ khá tốt. – AqD

+0

Bạn giả định rằng bạn có đủ nhận thức về những thứ khác cần thiết để hỗ trợ các API đó ... tất cả các phụ thuộc về cả mã gốc và mã được quản lý khác. Tôi không nghĩ nó đơn giản như bạn mong đợi. –

Trả lời

4

KHÔNG. DỪNG LẠI.

OK, vì đó không phải là những gì bạn muốn nghe, tiếp tục có nguy cơ của riêng bạn. :) Điều này chắc chắn không được hỗ trợ và IANAL vì vậy tôi không biết liệu nó có được cho phép theo thỏa thuận cấp phép hay không.

Có vẻ như vấn đề chính bạn gặp phải với các giải pháp hiện có là bạn không thể chọn các API riêng lẻ để thêm vào hồ sơ di động. Để làm điều đó, bạn có thể sử dụng ildasm trên các assembly tham chiếu hiện có, sau đó thêm vào các API bạn muốn (có thể bằng cách sao chép chúng từ các kết quả chạy ildasm trên một assembly khác), và sau đó sử dụng ilasm để tạo các phiên bản tham chiếu của riêng bạn lắp ráp với các API bổ sung đó.

Bạn sẽ cần phải trì hoãn ký hiệu và/hoặc tắt xác minh tên khóa mạnh cho các khóa cho hội đồng bạn sửa đổi theo cách này.

Một tùy chọn khác là sử dụng chuyển tiếp loại, như được mô tả trong câu trả lời của tôi here. Trong trường hợp đó, bạn sẽ kết thúc với mã chính của bạn đang được chia sẻ như là, với một sự phụ thuộc vào một DLL mà sẽ khác nhau cho mỗi nền tảng.

+0

Loại chuyển tiếp có vẻ là một ý tưởng hay. Vì vậy, về mặt lý thuyết, có thể quấn các phần giao nhau của tất cả các API và sau đó chuyển tiếp chúng tới các cụm chính xác. Nhưng sẽ có một công cụ để tự động hóa điều đó .. – AqD

10

Vì bạn sẽ không dùng NO hoặc STOP làm câu trả lời, hãy để tôi giải thích tại sao đây là ý tưởng tồi. Câu trả lời ngắn gọn là: nếu PCL không lộ ra một API thì thường là do nó không hoạt động.

Trước hết PCL không có bộ API riêng. PCL chỉ hiển thị các giao điểm của các API giữa một tập hợp các nền tảng bạn muốn nhắm mục tiêu. Bây giờ, có những trường hợp giao lộ cấp API sẽ mang lại nhiều API hơn so với những gì PCL tiết lộ. Có một số lý do tại sao điều này có thể xảy ra.

  1. API không có sẵn trên tất cả các nền tảng
  2. API có sẵn nhưng không thực sự làm việc
  3. API được định nghĩa trong hội đồng khác nhau

Người đầu tiên nên được rõ ràng . Bản thân PCL không phải là một nền tảng thực sự mà chỉ phơi bày những gì ở đó. Vì vậy, chúng tôi không thể cung cấp cho bạn các API không thực sự tồn tại trên tất cả các nền tảng mà bạn nhắm mục tiêu. Sau khi tất cả, chúng tôi vạch ra giao lộ.

Điều thứ hai nghe có vẻ hơi lạ nhưng thực sự xảy ra. Lấy ví dụ, nộp IO trên Windows Phone 7. mặc dù điều các File class là về mặt kỹ thuật có sẵn trên Windows Phone, đó là tài liệu như

This type is present to support the .NET Compact Framework infrastructure in Silverlight for Windows Phone, and it is not intended to be used in your application code.

Bạn có thể nói "những gì tôi quan tâm?" và chỉ cần thử nó nhưng sau đó bạn sẽ thấy rằng mô hình bảo mật trên điện thoại sẽ ngăn bạn truy cập vào các tệp bạn đang tìm kiếm. Vì vậy, việc hiển thị API này trong PCL sẽ không hữu ích. Trong thực tế, nhóm của chúng tôi tin rằng điều này thực sự sẽ làm tổn thương bạn bởi vì nó dẫn bạn xuống một con đường không di động.

Vấn đề thứ ba xung quanh các API đang được triển khai trong các hội đồng khác nhau có liên quan nhiều hơn một chút.Để hiểu tại sao đây là vấn đề bạn cần xem xét cách CLR xử lý các API nói chung. CLR không có khái niệm về việc nạp các kiểu đơn giản như Java chẳng hạn. Trong các kiểu .NET được thực hiện trong các assembly và để sử dụng chúng ("load chúng"), bạn cần phải nạp assembly xác định kiểu. Trong phần này, các kiểu có cùng một không gian tên đủ điều kiện nhưng sống trong các assembly khác nhau được xem là khác nhau. Ví dụ: loại MyNamespace.MyType, Assembly1MyNamespace.MyType, Assembly2. Xin lưu ý rằng bản thân hội chúng cũng có khái niệm về tên đầy đủ; nó bao gồm tên lắp ráp và mã thông báo khóa công cộng. Điều này cho phép hai công ty sản xuất cả một hội đồng gọi là "Foo" và không gây nhầm lẫn cho CLR (giả sử, tất nhiên, chúng được ký với các khóa khác nhau). Vì vậy, trong bản chất loại tải đòi hỏi một vài bước: việc tìm kiếm lắp ráp các loại được định nghĩa trong, tải lắp ráp, và sau đó tải các loại.

Các nền tảng .NET khác nhau sử dụng các khóa khác nhau cho các cụm nền tảng, ví dụ, mscorlib. Bây giờ bạn có thể tự hỏi làm thế nào bạn có thể sử dụng các loại từ Silverlight trên .NET Framework. Lý do cho điều đó là CLR có khái niệm về sự hợp nhất hội. Việc lắp ráp cho phép .NET Framework xử lý các tham chiếu đến mscorlib của Silverlight như là các tham chiếu đến phiên bản máy tính để bàn. Điều này là hợp lệ vì mscorlib của Silverlight được thiết kế để trở thành một tập hợp con của phiên bản .NET Framework (cho một sự kết hợp đặc biệt của các phiên bản).

Mặc dù điều này có vẻ giống như viên đạn bạc để thu hẹp tất cả sự khác biệt, nhưng thực tế là không. Theo thời gian, các nền tảng khác nhau đã chọn các yếu tố lắp ráp khác nhau. Lấy ví dụ, ICommand. Nó có sẵn trong .NET 4 và Silverlight 4. Tuy nhiên, trong WPF nó được thực hiện trong PresentationCore.dll trong khi Silverlight đặt nó trong System.Windows.dll. Để hiểu tại sao PCL không hiển thị ICommand khi bạn nhắm mục tiêu .NET 4 và Silverlight 4, hãy xem điều gì sẽ xảy ra nếu PCL phơi bày nó.

Trong PCL, chúng tôi phải đặt ICommnad trong một số hội đồng. Chúng ta có thể chọn sử dụng hội đồng Silverlight hoặc khung công tác đầy đủ. Không có vấn đề mà chúng ta sẽ chọn, loại sẽ không giải quyết trên nền tảng khác như PresenationCore.dll chỉ tồn tại trong .NET 4 và System.Windows.dll chỉ tồn tại trong Silverlight 4.

Chúng tôi giải quyết vấn đề này bằng cách cho phép tham khảo cho ICommand trong System.Windows.dll để thành công trên khuôn khổ đầy đủ. Làm thế nào mà chúng ta làm điều này? Câu trả lời là nhập chuyển tiếp. Loại chuyển tiếp cho phép một hội đồng để nói "Tôi xác định một loại Foo". Khi CLR cố gắng nạp kiểu Foo từ assembly đó, assembly thực sự nói "không, không - kiểu Foo thực sự được định nghĩa trong thanh Assembly khác". Nói cách khác, lắp ráp Foo có chứa một cái gì đó giống như một con trỏ đến phiên bản của loại Bar. Chúng tôi gọi những con trỏ đó là các mục chuyển tiếp.

Khái niệm này cho phép chúng tôi giải quyết sự không phù hợp của ICommand bằng cách thêm System.Windows.dll vào khung làm việc đầy đủ có chứa một loại chuyển tiếp đến triển khai thực tế. PCL hiện cung cấp cho bạn ICommand trong System.Windows.dll và có thể chắc chắn rằng các yêu cầu tải kiểu có thể thành công trên cả hai .NET Framework cũng như Silverlight. Tuy nhiên, điều này đòi hỏi phải nhắm đến ít nhất .NET Framework 4.5 vì các phiên bản trước không có kiểu chuyển tiếp.

Đối với tất cả các API cần được hiển thị nhưng chúng tôi không làm việc cùng với chủ sở hữu nền tảng để thu hẹp khoảng trống. Chúng tôi có về cơ bản hai chiến lược cho rằng:

  1. Chúng tôi yêu cầu chủ sở hữu nền tảng để thêm API thiếu hoặc gõ chuyển tiếp
  2. Chúng tôi tàu một việc thực hiện di theo kiểu out-of-band. Lấy ví dụ Async hoặc HttpClient.

Tuy nhiên, "chỉ cần" thêm nó vào PCL không hoạt động.

EDIT: Nếu bạn bỏ lỡ một tính năng trong PCL, bạn luôn có thể bỏ chặn chính mình. Thử nghiệm của chúng tôi Daniel có written a blog post hiển thị một số kỹ thuật bạn có thể sử dụng.

+0

Cảm ơn. Nhưng cho đến khi Microsoft bổ sung những gì tôi muốn vào PCL, thì không có gì thay thế cho tôi. Tôi không thể lấy một giải pháp phi giải pháp. – AqD

+0

Bạn có thể giải quyết vấn đề này mà không cần phải tinh chỉnh các bộ tham chiếu PCL. Người thử nghiệm của chúng tôi đã viết một bài đăng trên blog tuyệt vời về các giải pháp có thể có. Tôi đã thêm nó vào câu trả lời. –

Các vấn đề liên quan