2012-02-28 74 views
6

Tôi đang tạo một lớp bao bọc trong .NET (VB.NET như nó xảy ra nhưng đều liên quan đến C#) được tiếp xúc với COM và một trong các thuộc tính mà tôi đang cố gắng bọc là một biến thể. Tôi nghĩ tôi sẽ chỉ có thể sử dụng một đối tượng, nhưng tôi nhận được một lỗi:Hiển thị các thuộc tính trong .NET cho Interop

Public Property FieldValue([vFieldID As Object = -1]) As Object cannot be exposed to COM as a property 'Let'. You will not be able to assign non-object values (such as numbers or strings) to this property from Visual Basic 6.0 using a 'Let' statement.*

kê khai tài sản của tôi trông như thế này:

Public Property FieldValue(Optional ByVal vFieldID As Object = -1) As Object 
    Get 
     Return _objVAccess.FieldValue(vFieldID) 
    End Get 
    Set(ByVal value As Object) 
     _objVAccess.FieldValue = value 
    End Set 
End Property 

Tài sản của tôi thực sự trả về một giá trị từ cơ sở dữ liệu mà có thể là số nguyên, chuỗi, ngày tháng, v.v. do đó không phải là một đối tượng theo điều khoản COM. Có cách nào để giải quyết vấn đề này cho phép tài sản được không?

+0

Bạn đã thử sử dụng 'ValueType' thay vì' Object' chưa? –

+0

MSDN mô tả cách thực hiện việc này với cấu trúc, nhưng tôi không tự mình làm theo đầy đủ: http://msdn.microsoft.com/en-us/library/2x07fbw8(v=vs.71).aspx –

+0

bằng cách nào đó liên quan: http://stackoverflow.com/q/26385964/2140173 –

Trả lời

28

Tự động hóa COM hỗ trợ thuộc tính mặc định, thuộc tính đã giải quyết 0. Điều này được sử dụng trong mã VB6 để tạo hiệu ứng tuyệt vời, tạo ra mã thực sự nhỏ gọn. Một ví dụ điển hình là:

rs!Customer = "foo" 

Đó là đường cú pháp cho:

rs.Fields.Item("Customer").Value = "foo" 

Ba thuộc tính mặc định được sử dụng ở đây mà không bị nêu tên trong báo cáo kết quả ban đầu. Giao diện Recordset có thuộc tính Fields làm thuộc tính mặc định, tạo ra tham chiếu giao diện Fields. Trong đó có thuộc tính Item là thuộc tính mặc định (được lập chỉ mục) tạo ra một tham chiếu giao diện Field. Trong đó có thuộc tính Giá trị làm thuộc tính mặc định, tạo ra một biến thể.

Điều này rất hay. Giá của đường cú pháp cực đoan như thế này tuy nhiên là sâu răng. Có một sự mơ hồ về cú pháp trong một tuyên bố như:

Dim obj 
obj = someObject 

Điều gì được dự định ở đây? Bạn có muốn gán tham chiếu someObject cho obj không? Hoặc bạn có muốn chỉ định thuộc tính mặc định của someObject không? Rất khác nhau, loại obj sẽ hoàn toàn khác. Điều này đã được giải quyết trong VB6 với từ khóa Đặt. Nếu bạn muốn gán tham chiếu đối tượng sau đó bạn phải viết:

Set obj = someObject 

Và bạn bỏ qua Đặt hoặc sử dụng Hãy một cách rõ ràng nếu bạn có nghĩa là gán giá trị tài sản mặc định. Đó là khá yucky và đã bedeviled newbie Visual Basic và VB script lập trình trong một thời gian rất dài.

Tự động hóa COM thực hiện việc này bằng cách cho phép thuộc tính có hai bộ định vị.Tương ứng propputpropputref trong IDL trong đó propputref là đối tượng gán một đối tượng. Bạn cũng có thể nhìn thấy điều này trong định nghĩa IDispatch, phương thức IDispatch :: Invoke() phân biệt giữa hai phương thức này với DISPATCH_PROPERTYPUT và DISPATCH_PROPERTYPUTREF.

Chuyển tiếp tới VB.NET, Microsoft đã quyết định rằng sự mơ hồ quá đau đớn và loại bỏ khái niệm về thuộc tính không được lập chỉ mục mặc định. Mà blissfully cũng đã nghỉ hưu từ khóa Set. Tuy nhiên, điều này tạo ra một vấn đề mới, không còn cách nào khác để viết một lớp [ComVisible] có thể có một thuộc tính của kiểu Object với một setter chấp nhận một tham chiếu đối tượng. Cú pháp ngôn ngữ cho phép chỉ có một setter và lớp interop COM trong CLR thiếu hệ thống ống nước để tổng hợp hai. Đáng chú ý là đây chỉ là một cảnh báo, bạn vẫn nhận được setter propput, bạn chỉ sẽ không nhận được setter propputref. Mà theo như tôi có thể nói là tất cả các bạn muốn anyway.

Xác định giao diện trong lớp giả VB6 hoặc bằng cách viết IDL một cách rõ ràng và biên dịch nó với midl.exe thực sự là một cách để đi xung quanh cảnh báo. Như được hiển thị bởi John Rivard trong this question.

+0

Cuối cùng tôi thấy cách SET/LET thực sự hoạt động và tại sao. Cảm ơn nhiều. – quetzalcoatl

+0

Điều này. Đau đầu của tôi cuối cùng đã đi với lời giải thích này. – Scorchio

+0

Vì vậy DISPATCH_PROPERTYPUT, thay vì đặt trực tiếp thuộc tính, sẽ đặt thuộc tính mặc định của đối tượng được tham chiếu bởi thuộc tính? – Medinoc

2

Bạn đã thử sử dụng thuộc tính MarshalAs?

Bạn sẽ có thể áp dụng nó như thế (xin lỗi nếu tôi có một sai lầm cú pháp, tôi thường sử dụng C#):

Public Property FieldValue(Optional ByVal vFieldID As Object = -1) As <MarshalAsAttribute(UnmanagedType.Struct)> Object 
    Get 
     Return _objVAccess.FieldValue(vFieldID) 
    End Get 
    Set(ByVal value As Object) 
     _objVAccess.FieldValue = value 
    End Set 
End Property 

Điều đó sẽ nói với marshaller để lộ tài sản như một cấu trúc VARIANT.

Bạn có thể phải áp dụng các thuộc tính bổ sung cho kích thước cấu trúc, v.v., nhưng tôi nghĩ đây là hướng bạn có thể sử dụng để giải quyết vấn đề của mình.

+0

Tôi nhận được cảnh báo tương tự trong Visual Studio và tôi không thể ghi vào thuộc tính trong VB6 –

+0

Tôi đã sử dụng điều này cho một vấn đề liên quan, phơi bày số nguyên 64 bit đến một ứng dụng VB6 thông qua COM. Đây là cú pháp: Property Size() Như Object –

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