2013-05-17 31 views
6

Tôi đã viết một thư viện lớp COM có thể nhìn thấy trong C# 4.0 mà tôi đang tiêu thụ với VB6. Điều này hoạt động, chỉ khi tôi mở trình duyệt đối tượng VB6 và nhìn vào các thành viên bị lộ, tôi thấy một sự kiện cho mỗi và mọi thành viên tiếp xúc duy nhất ... nhưng mã C# không xác định bất kỳ.VB6/COM Interop: các sự kiện này đến từ đâu?

Điều này có bình thường không? Tôi có làm điều gì sai?

[ClassInterface(ClassInterfaceType.None)] 
[ComSourceInterfaces(typeof(IMyClass))] 
public class MyClass : IMyClass 
{ 
    public void DoSomething(string someParam) 
    { 
     ... 
    } 
} 

public interface IMyClass 
{ 
    void DoSomething(string someParam); 
} 

Việc lắp ráp được ký kết với một chìa khóa tên mạnh mẽ và AssemblyInfo.cs có tập [assembly: ComVisible(true)] thuộc tính, nhưng tôi không chắc chắn nó có liên quan gì đến vấn đề này.

Khi tôi nhìn vào trình duyệt đối tượng trong VB6, tôi sẽ mong đợi để xem DoSomething(string) như một thành viên của MyClass, và tôi làm, tuy nhiên tôi cũng nhìn thấy một sự kiện với một chữ ký phù hợp cho tất cả các tiếp xúc , như Event DoSomething(someParam As String) là thành viên của MyClass.

Thậm chí nhiều hơn khó hiểu (với tôi ít nhất), tài sản cũng có một "phù hợp với" sự kiện (chỉ có thể nói từ biểu tượng sét chút mặc dù) - nếu MyClass định nghĩa một tài sản như thế này:

public string SomeProperty { get; set; } 

Các VB6 đối tượng trình duyệt sẽ nói rằng "sự kiện" được định nghĩa là Property SomeProperty As String, mà lá tôi flabbergasted - làm thế nào để một "tài sản" 1) được nhân đôi và 2) trùng lặp được hiển thị với một "sự kiện" biểu tượng trong trình duyệt đối tượng? Điều tương tự cũng áp dụng cho các thuộc tính chỉ nhận được, trong đó có đối tác "thuộc tính/sự kiện" chỉ đọc của họ.

Các sự kiện này đến từ đâu và làm cách nào để loại bỏ chúng?

CẬP NHẬT Một hình ảnh đáng giá ngàn lời nói:

COM Interop - bogus events

CẬP NHẬT Các điều saiComSourceInterfaces thuộc tính được nhầm lẫn được sử dụng ở vị trí của một thuộc tính ComDefaultInterface. Trao đổi các cựu cho sau này cung cấp cho các kết quả mong đợi:

COM Interop - correct members

+0

Vì đây thực chất là lỗi đánh máy, tôi sẽ bỏ phiếu để đóng nội dung này là quá địa phương hóa. Tôi khuyên bạn nên xóa nó. – Deanna

+0

@Deanna typo thực sự, nhưng tôi đã học được điều gì đó về việc phơi bày các sự kiện cho COM .. Tôi đoán bạn nói đúng, phải có nhiều bài viết SO về việc phơi bày các sự kiện .net cho COM ... ngoại trừ có hai bài đăng chất lượng ở đây không xứng đáng bị xóa :) –

+2

@Deanna Tôi không nghĩ chúng ta nên xóa cái này. Đó là một lỗi đánh máy, nhưng nó có thể gây nhầm lẫn cho những người khác là người mới đến COM interop. Tôi đã học được điều gì đó từ nó. – MarkJ

Trả lời

8

Bằng cách vượt qua typeof(IMyClass) như một cuộc tranh cãi với ComSourceInterface thuộc tính bạn đang nói rằng tất cả mọi thứ trong IMyClass là một sự kiện.

Nếu bạn không muốn giao diện sự kiện cho lớp của mình, hãy xóa thuộc tính ComSourceInterface.

Nếu bạn làm muốn phơi bày các sự kiện từ C# lớp học của bạn để VB sau đó làm như sau:

Khi bạn tạo ra một lớp có thể nhìn thấy COM bạn cũng sẽ muốn tạo một giao diện định nghĩa chỉ là xử lý sự kiện cho lớp học của bạn. Lớp của bạn nên được trang trí với COMSourceInterface chỉ định giao diện trình xử lý sự kiện của bạn và nên xác định các sự kiện của bạn và triển khai giao diện trình xử lý sự kiện. Xem How To: Raise Events Handled by a COM sink để biết ví dụ khác.

[GuidAttribute("1A585C4D-3371-48dc-AF8A-AFFECC1B0967") ] 
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] 
public interface MyEvents 
{ 
    void ConnectedEvent(string state); 
} 


[ComSourceInterfaces(typeof(MyEvents))] 
public class MyClass 
{ 
    public event Action<string> ConnectedEvent; 

    public MyClass() { } 

    public void DoSomething(string state) 
    { 
     if (ConnectedEvent != null) 
      ConnectedEvent(state); 
    } 
} 

Xem thêm: Murat's Corner: Exposing COM Events

+1

Tôi chưa bao giờ tiếp xúc với sự kiện C# đến COM, cảm ơn bài đăng này tôi chắc chắn sẽ quay lại khi tôi cần làm như vậy, nhưng tôi không thể chấp nhận nó như một câu trả lời vì * không có sự kiện ở bất kỳ đâu trong mã C# * ... và câu hỏi đặt ra là nơi các sự kiện COM/VB6 đó xuất hiện từ đâu; Tôi không nghĩ rằng một upvote được bảo hành cho * này * câu trả lời (như là) trên * câu hỏi này *. Nhưng đây sẽ là một câu trả lời tuyệt vời nếu tôi hỏi về việc phơi bày các sự kiện C# với COM/VB6; nếu bạn định chỉnh sửa câu trả lời của mình, vui lòng chỉnh sửa bài đăng của bạn bằng cách thêm vào bài đăng đó; nó vẫn là thông tin có giá trị, mặc dù một chút chủ đề. –

+3

@retailcoder nhưng bạn đã làm, với thuộc tính 'ComSourceInterfaces'. Điều này nói với tlbexport rằng đối tượng của bạn có thể nguồn sự kiện cho giao diện đó. – Deanna

+1

@retailcoder Hàm ý trong câu trả lời của tôi là bạn đã chỉ định một giao diện sự kiện bằng cách sử dụng thuộc tính ComSourceInterface. Xóa nó nếu bạn không muốn để lộ điểm kết nối sự kiện. –

8

Bạn đang tìm hiểu về cơ bản là không có bất cứ điều gì đặc biệt về các sự kiện trong COM. Giống như bất cứ thứ gì trong COM, các sự kiện được hỗ trợ bởi một giao diện. Điều duy nhất đặc biệt về một giao diện chỉ định các phương thức sự kiện là nó được đánh dấu bằng thuộc tính [source] trong thư viện kiểu. Đó là tất cả các thuộc tính [ComSourceInterfaces] hiện, được công nhận bởi Tlbexp.exe khi nó tạo ra thư viện kiểu.

Cũng không có bất kỳ điều gì đặc biệt đặc biệt về các thuộc tính trong COM. Chúng hoạt động giống như trong .NET, chúng được triển khai với các phương thức . Một getter và một phương thức setter.

Vì vậy, VB6 xem thư viện kiểu của bạn và hài lòng về lớp có sự kiện vì nó có giao diện với thuộc tính [source]. Và hạnh phúc về giao diện đó có các phương thức, tất cả chúng có thể có, do đó, nó giả định đó là các phương thức chạy khi sự kiện được nâng lên. Nó không phải là đủ thông minh để nhận ra rằng những phương pháp cũng là accessors cho một tài sản, nó giả định rằng các loại thư viện tác giả biết những gì anh ta đang làm.

Sự kiện được gọi là "điểm kết nối" trong COM. Google IConnectionPoint để tìm hiểu thêm về nó. Nếu bạn đã từng tạo một thành phần WinRT với các trình truy cập sự kiện tùy chỉnh thì bạn cũng sẽ thấy rằng các sự kiện COM có rất ít điểm chung với các sự kiện .NET.

Anyhoo, giải pháp thay thế rất đơn giản, chỉ sử dụng [ComSourceInterface] khi bạn tăng sự kiện.

+0

Và khi lớp học xuất phát từ loại chung, ... đó là lý do tại sao * ComSourceInterfaceAttribute * ... không mong đợi "tác dụng phụ" này! Cảm ơn lời giải thích, tôi đã học được điều gì đó ngày hôm nay! –

+0

COM không hỗ trợ Generics, chỉ có các lớp cụ thể mà không có một đối số kiểu có thể là [ComVisible]. –

+0

Ah! Có lỗi của tôi: Tôi trộn lẫn '[ComSourceInterface]' và '[ComDefaultInterface]' - "Xuất khẩu thư viện kiểu đã gặp phải một kiểu xuất phát từ một kiểu generic và không được đánh dấu là [...] ClassInterfaceType.None [... ] Xem xét [...] để lộ giao diện rõ ràng làm giao diện mặc định cho COM bằng thuộc tính [ComDefaultInterface]. " ... Tôi biết COM không hỗ trợ Generics, tôi đã viết "khi một lớp * xuất phát từ * một loại chung chung". –

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