2010-07-22 2 views
16

Tôi đã luôn luôn đánh dấu các hội đồng .NET của tôi là hiển thị với COM với [assembly: ComVisible(true)], nghĩ rằng tôi không bao giờ biết khi nào một người nào đó có thể cần gọi chúng từ COM. Tôi cũng bắt đầu sử dụng FxCop và bắt đầu thấy cảnh báo này từ việc phân tích mã:Tại sao đánh dấu một hội đồng ComVisible (đúng) không khuyến khích?

CA1017: Microsoft.Design: Vì 'MyLibrary.dll' hiển thị các loại hiển thị bên ngoài, đánh dấu nó bằng ComVisible (false) ở cấp hội đồng và sau đó đánh dấu tất cả các loại trong lắp ráp nên được tiếp xúc với khách hàng COM với ComVisible (true)

có một số lý do tại sao bạn sẽ không đơn giản chỉ muốn tất cả các loại công cộng của bạn tiếp xúc với COM? Tôi đoán rằng có, nhưng tôi không thể tưởng tượng được lý do này là gì. Nếu bất cứ điều gì, nó có vẻ bất tiện.

Trả lời

22

Tôi đã không làm việc với COM interop trong một thời gian, nhưng trước đây tôi luôn làm việc với triết lý "chọn tham gia" thay vì "chọn không tham gia" thay vì làm cho mọi thứ COM hiển thị, tôi đánh dấu lắp ráp như không COM hiển thị. Sau đó tôi tập trung vào việc hiển thị các thành viên loại (có nghĩa là bằng cách chọn tham gia), và đảm bảo rằng API được tiếp xúc là lành mạnh cho COM (ví dụ COM không hỗ trợ Genrics, quá tải phương thức hoặc các hàm tạo tham số) và nó cũng có đã được thử nghiệm với COM trong tâm trí. Bằng cách này, việc đưa ra một API đến COM được thực hiện theo cách nghiêm ngặt, được kiểm tra, giới hạn và duy trì.

Điều này trái ngược với việc làm cho mọi thứ có thể nhìn thấy và sau đó lo lắng về bất kỳ vấn đề tiềm ẩn nào sau này, lưu ý rằng nếu bạn đã tiếp xúc mọi thứ thì có thể có khớp nối với người dùng giao diện COM mà bạn không mong đợi và bây giờ gặp khó khăn trong việc sao lưu.

Từ ký ức một vài ví dụ về hậu quả bất ngờ:

  1. Khi xuất phương pháp quá tải, họ được xuất khẩu và được đặt tên theo mặc định với một số thứ tự ví dụ OverloadedMethod1, OverloadedMethod2, vv Nếu bạn refactor mã của bạn và thay đổi thứ tự của các phương pháp của bạn hoặc chèn một quá tải, vv, bạn đang gặp rắc rối với bất cứ ai đã sử dụng các phương pháp này từ giao diện COM trước đó của bạn. OverloadedMethod1 và OverloadedMethod2 có thể đã được đổi chỗ.

  2. Các lớp được tiếp xúc với COM phải có hàm tạo không tham số. Nếu không có một bài kiểm tra đơn vị tại chỗ duy trì hợp đồng này, sau đó nó rất dễ dàng để thay đổi lớp đó vào một ngày sau đó để nó không có một constructor parameterless và do đó phá vỡ người sử dụng giao diện COM của bạn.

Điều quan trọng là xuất giao diện COM không có miễn phí vì có sự không tương thích và yêu cầu phải được đáp ứng. Điều này phải được cả hai suy nghĩ về và sau đó duy trì. Cảnh báo CA1017 là ám chỉ đến điều này.

5

Với sự ra đời của Generics và các loại tiên tiến khác, nó là phổ biến hiện nay cho các phương pháp để lộ loại mà không thể được COM có thể nhìn thấy hơn là cho họ để lộ loại mà thể.

Phương pháp được đề xuất trong CA1017 nhằm khuyến khích bạn phơi bày chỉ các loại mà bạn có ý định để được tiếp xúc với COM.

2

Đánh dấu cụm không phải là hiển thị COM rất hữu ích when you have a bunch of public classes inside that you don't want to expose to COM. Ví dụ, những lớp đó có thể là các lớp proxy của một web serive mà assembly của bạn tiêu thụ. Hoặc là bạn đánh dấu triệt để từng lớp như vậy không hiển thị COM hoặc bạn chỉ đánh dấu assembly không phải là COM và sau đó đánh dấu từng lớp để lộ ra COM. Đó là một mức độ kiểm soát cao hơn và ít bảo trì hơn.

4

Để tham khảo, nếu không có mức lắp ráp ComVisibleAttribute được áp dụng, tất cả các lớp công khai được giả định là COM Visible. Không đánh dấu một hội đồng như [assembly: ComVisible(false)] thường sẽ dẫn đến việc cảnh báo Phân tích Mã sau, ngay cả đối với các loại không được đánh dấu [ComVisible(true)]:

CA1405: COM loại có thể nhìn thấy các loại cơ sở nên COM có thể nhìn thấy

1

Nó rất dễ dàng và được trên MSDN. Đây là cách làm thế nào để sửa chữa cảnh báo này:

using System; 
using System.Runtime.InteropServices; 

[assembly: ComVisible(false)] 
namespace InteroperabilityLibrary 
{ 
    [ComVisible(false)] 
    public class BaseClass 
    { 
     public void SomeMethod(int valueOne) {} 
    } 

    // This class violates the rule. 
    [ComVisible(true)] 
    public class DerivedClass : BaseClass 
    { 
     public void AnotherMethod(int valueOne, int valueTwo) {} 
    } 
} 

Nếu cơ sở lớp học là trong bất kỳ dll mà bạn đang đề cập trong mã của bạn. Sau đó, Make [COMVisibible (True)] cho lớp dẫn xuất. Nó hoạt động trong kịch bản của tôi.

+0

Câu hỏi không phải là cách khắc phục. Câu hỏi đặt ra là cảnh báo này đang cố gắng cảnh báo về điều gì trước tiên. – sharptooth

+0

AS MSDN cũng xác định nguyên nhân gốc rễ của cảnh báo này, tức là "Kiểu hiển thị mô hình đối tượng thành phần (COM) có nguồn gốc từ loại không hiển thị COM". –

+1

Đó không phải là một vấn đề khó tìm thấy ngay cả khi không có cảnh báo. Một phần rất thô lỗ và tinh tế là bạn sẽ có tất cả các công cụ được đăng ký trong COM với một hội đồng ComVisible. – sharptooth