2011-08-09 28 views
6

Tôi đã nhận thấy rằng nếu tôi tạo một thành phần .NET để lộ ra một ArrayList, thì ArrayList đó đi qua COM Interop và có sẵn trong các ngôn ngữ kịch bản như VBScript.Tại sao ArrayList làm việc với COM Interop, nhưng IList <T> thì không?

Generics, chẳng hạn như IList<T> dường như không hoạt động.

Tại sao điều này và có cách nào để làm cho một loại chung thành công chảy qua COM Interop đến một công cụ tạo tập lệnh không?

+2

Vì COM không hỗ trợ Generics. Hãy xem [this] (http://stackoverflow.com/questions/1862497/c-exposing-class-to-com-generic-collections) và [this] (http://stackoverflow.com/questions/ Câu hỏi 269581/giải pháp thay thế-cho-chung-bộ sưu tập-cho-com-interop). –

Trả lời

5

Generics được thêm vào .NET 2.0 và COM tồn tại trước .NET 1.0.
(Và là công nghệ .NET nhằm để thay thế.)

COM không bao giờ có Generics, và do đó bạn không thể tiếp xúc với họ.
Không có ngôn ngữ COM nào (C++, VB6, Delphi) đều có generics để bạn không thể mong đợi chúng được tiêu thụ.
(Vâng, C++ đã có mẫu nhưng họ hoàn toàn một con thú khác nhau, và COM chỉ có nghĩa là giao diện.)

Phơi bày các bộ sưu tập như một ArrayListsolution cho vấn đề này, bạn không thể làm việc xung quanh nó.

Tuyên bố từ chối: Tôi không có chuyên gia về COM nên phần còn lại của câu trả lời là dựa trên dự đoán của tôi.

COM không bao giờ “đã” ArrayList s, đúng, nhưng vì thế nó không bao giờ có bất kỳ của các lớp trong .NET Framework, bởi vì nó không phải là một khuôn khổ riêng của mình. Tuy nhiên, một số loại .NET có được trong các thư viện kiểu được xuất, và một số thì không. Còn các lớp .NET Framework thì sao? Vâng, ArrayList[ComVisible]List<T> thì không.

Tại sao?

COM works via interfaces và Ngôn ngữ định nghĩa giao diện không có đầu mối về generics và không hỗ trợ chúng. Các ngôn ngữ hỗ trợ COM, chẳng hạn như VB6 hoặc C++, sẽ không biết phải làm gì với các generics.

Nếu có cách tạo giao diện cho List<T>, nó sẽ không chứa T trong đó để về cơ bản không có điểm cố gắng vạch trần loại chung. Các lựa chọn thay thế tưởng tượng có thể có cho điều này sẽ là:

  • Tạo phiên bản giao diện "cụ thể" cho loại chung, ví dụ: IListOfString cho List<string>
  • Xóa thông tin loại chung chung (giống như Java không biên dịch) và thay thế T bằng object.

Tùy chọn đầu tiên là không khả thi vì bê tông T loại có thể không được biết đến ở biên soạn (đọc: Reflection), và List<T> không có một thuộc tính [ComVisible] vào nó anyway.

Lựa chọn thứ hai là thực sự loại càng tốt vì bạn có thể provide your own class interface with IList and ICollection properties:

[ComVisible(true)] 
public interface IPerson 
{ 
    string Name { get;set;} 
    DateTime Entered { get;set;} 
    IList NickNamesList { get;} 
    ICollection NickNamesCollection { get;} 
} 

[ComVisible(true)] 
[ClassInterface(ClassInterfaceType.AutoDual)] 
[ComDefaultInterface(typeof(IPerson))] 
public class Person:IPerson 
{ 
    [ComVisible(false)] 
    public List<string> NickNames 
    { 
     get { return _NickNames; } 
     set { _NickNames = value; } 
    } 
    private List<string> _NickNames = new List<string>(); 

    #region IPerson Members 
    IList IPerson.NickNamesList 
    { 
     get { return this.NickNames; } 
    } 

    ICollection IPerson.NickNamesCollection 
    { 
     get { return this.NickNames; } 
    } 
    #endregion 
    .... 
} 

Đây là một cách giải quyết và không trả lời câu hỏi của bạn mặc dù.

Tôi thực sự tự hỏi liệu bạn có thể lấy được lớp học StringList từ List<string> và đánh dấu nó là [ComVisible(true)]. Bạn có thể muốn kiểm tra điều đó.

+0

Tôi không thể chấp nhận điều đó. Microsoft đã làm công việc ArrayList (COM không bao giờ có ArrayLists) - vì vậy nó phải có thể bằng cách nào đó làm cho các loại khác hoạt động. Generics có các loại cụ thể khi chạy. Cơ chế làm cho ArrayList hoạt động như thế nào? –

+0

Tôi không có chuyên gia về COM nhưng tôi đã chỉnh sửa câu trả lời để kết hợp một số dự đoán của tôi. –

+0

Giả sử ràng buộc trễ (IDispatch) và xem liệu điều đó có đặt nghiêng khác về mọi thứ không. Mỗi kiểu .NET là một kiểu cụ thể khi chạy, do đó, miễn là ràng buộc trễ được sử dụng từ thành phần COM, nó sẽ có thể 'thấy' loại bê tông có nguồn gốc từ một generic. Cho rằng COM có hệ thống kiểu riêng của nó, một số chuyển đổi là cần thiết giữa các loại .NET và các kiểu COM. Tôi đã làm một số đọc ngày hôm nay và bây giờ tôi tự hỏi nếu nó có thể có thể sử dụng một marshaller tùy chỉnh để 'lộ' một loại chung để COM? Kiến thức của tôi về COM thực sự yếu, vì vậy tôi thực sự chỉ chụp trong bóng tối. –

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