2011-10-27 27 views
5

Chúng tôi đã phát triển .NET Assembly lưu trữ thông tin dịch ngôn ngữ và nó cần được ứng dụng VB6 sử dụng.Làm cách nào để bảo tồn tính tương thích nhị phân cho một .NET Assembly trình bày giao diện COM?

Chúng tôi muốn có thể thay đổi thông tin dịch mà không phải biên dịch lại ứng dụng.

Bản dịch được cung cấp bởi một lớp hai phần được gọi là LanguageServices.

Một tệp là phương pháp thư viện không thay đổi, phương pháp kia là tất cả các thuộc tính được tạo tự động từ tệp resx và regx được tạo từ cơ sở dữ liệu thông tin dịch ngôn ngữ.

Tất cả điều này phát sinh từ sự cần thiết phải có một cơ sở dữ liệu trung tâm của các bản dịch có thể được lập trình "phẳng" thành định dạng có thể được sử dụng bởi từng ứng dụng khác nhau của chúng tôi.

Bây giờ, tôi có thể giải quyết vấn đề này bằng cách bỏ qua nó và thực hiện theo cách khác. Trong thực tế, tôi chỉ có thể loại bỏ danh sách các thuộc tính được tạo tự động và vấn đề sẽ biến mất.

Những gì tôi quan tâm là làm thế nào tôi có thể giải quyết vấn đề này, đó là như sau:

Nếu chúng ta thêm các nhãn dịch mới vào cơ sở dữ liệu (từ này trong từ này trở nên RẰNG WORD) nó bổ sung thêm tài sản mới vào lớp, mà lần lượt thêm các thuộc tính tiếp xúc mới vào giao diện COM.

Thuộc tính được thêm vào giữa giao diện COM, do đó phá vỡ khả năng tương thích nhị phân. Chúng được thêm vào ở giữa bởi vì trình biên dịch C# kết hợp phần động của lớp một phần với phần tĩnh của lớp một phần. Những gì tôi cần nó làm là nối chúng theo cách khác xung quanh hoặc trình bày rõ ràng thứ tự trong các tập tin C#. Tôi nghĩ rằng thiết lập các DispIDs một cách rõ ràng trên phần tĩnh của lớp sẽ làm điều đó, nhưng nó đã không.

Dưới đây là cặp tệp IDL được tạo bởi quá trình xây dựng:

Đây là IDL trước khi tôi thêm thuộc tính mới.

http://pastebin.com/qPvcUV9z

Và đây là IDL sau khi một tài sản mới đã được thêm vào và khả năng tương thích được chia:

http://pastebin.com/K2MuqtYV

Sự khác biệt chính xác là bit này bị đẩy vào giữa:

[id(0x60020039), propget] 
HRESULT Jn_ExactCaseMatch([out, retval] VARIANT_BOOL* pRetVal); 
[id(0x6002003a), propget] 
HRESULT Jn_Regex([out, retval] VARIANT_BOOL* pRetVal); 
[id(0x6002003b), propget] 
HRESULT Jn([out, retval] BSTR* pRetVal); 

Và tôi nghĩ rằng đó là khả năng m, nó thay đổi thứ tự của các phương thức. Tôi nghĩ rằng để có thể được overriden bằng cách định nghĩa một cách rõ ràng DispID (bạn có thể thấy rằng tất cả mọi thứ từ HRESULT Culture([in] ICultureInfo* pRetVal); trở đi có một id bắt đầu từ 0.

Dưới đây là mã C# mà được viết/tạo: ILanguageServices.cs: Tự động tạo ra giao diện.

[Guid("547a7f6e-eeda-4f77-94d0-2dd24f38ba58")] 
public partial interface ILanguageServices 
{ 
    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean Offence_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean Offence_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string Offence { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean Colour_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean Colour_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string Colour { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean DebtManagementSystem_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean DebtManagementSystem_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string DebtManagementSystem { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean DateOfContravention_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean DateOfContravention_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string DateOfContravention { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean ContraventionDetails_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean ContraventionDetails_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string ContraventionDetails { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean Income_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean Income_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string Income { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean Hold_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean Hold_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string Hold { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean CivilEnforcementOfficer_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean CivilEnforcementOfficer_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string CivilEnforcementOfficer { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean PCNDebt_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean PCNDebt_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string PCNDebt { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean OnHold_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean OnHold_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string OnHold { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean DatePutOnHold_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean DatePutOnHold_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string DatePutOnHold { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean HoldCode_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean HoldCode_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string HoldCode { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean DateHoldExpires_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean DateHoldExpires_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string DateHoldExpires { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean PutOnHoldByUserName_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean PutOnHoldByUserName_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string PutOnHoldByUserName { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean CurrentState_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean CurrentState_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string CurrentState { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean Vrm_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean Vrm_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string Vrm { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean State_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean State_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string State { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean CurrentStatechangedd2d2d4_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean CurrentStatechangedd2d2d4_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string CurrentStatechangedd2d2d4 { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean SimonTest_ExactCaseMatch { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    System.Boolean SimonTest_Regex { get; } 

    /// <summary> 
    /// 
    /// </summary> 
    string SimonTest { get; } 
} 

ILanguageServices_Static.cs: Phần không thay đổi của giao diện

public partial interface ILanguageServices 
{ 
    [DispId(0)] 
    ICultureInfo Culture { get; set; } 
    [DispId(1)] 
    IResourceManager ResourceManager { get; } 
    [DispId(2)] 
    ICultureInfo[] GetCultures(System.Globalization.CultureTypes enCultureTypes); 
    [DispId(3)] 
    ICultureInfo GetCultureInfo(int LCID); 
    [DispId(4)] 
    ICultureInfo CurrentCulture { get; } 
    [DispId(5)] 
    string TranslateString(string rawString, bool searchInsideString); 
    [DispId(6)] 
    string TranslateString(string rawString); 
} 

Suy nghĩ về điều đó, tôi có thể chỉ làm cho nó không phải là một phần. Chỉ cần thay đổi xslt đã tạo phần được tạo tự động để bao gồm phần tĩnh. Nó chỉ là gọn gàng để giữ cho nó riêng biệt.

Bất kể ai cũng có thể cho tôi biết tại sao nó không hoạt động và cách giữ quyền kiểm soát chặt chẽ hơn đối với giao diện COM? Đặt hàng đúng cách các phương pháp có vẻ như vậy ... bleugh.

Xin cảm ơn,

J1M.

+2

[DispId] chỉ hoạt động nếu mã khách hàng đang sử dụng kết buộc muộn. Rõ ràng là không. Đây là gót chân Achilles của COM, thứ tự bảng v là rất quan trọng. Thay đổi [Hướng dẫn] là tốt nhất. –

Trả lời

2

Từ C# Langauge Specification Version 4 Mục 10.2.6

Trật tự của các thành viên trong một loại hiếm khi đáng kể cho mã C#, nhưng có thể có ý nghĩa khi giao tiếp với ngôn ngữ và môi trường khác. Trong những trường hợp này, thứ tự của các thành viên trong một loại được khai báo trong nhiều phần là không xác định.

Vì vậy, không có quy định nào trong laguage C# để kiểm soát thứ tự của các thành viên thuộc loại, khác với thứ tự chúng được khai báo. Trong một loại được khai báo một phần, thì thứ tự là completley undefined.

Vì vậy, kết luận ở đây là không sử dụng khai báo từng phần cho các giao diện mà bạn sắp hiển thị với COM. Không có cách nào để kiểm soát thứ tự thành viên giao diện, và vì nó không được xác định trong ngôn ngữ, thứ tự thành viên kết quả có thể thay đổi bất cứ lúc nào.

+0

Vâng, tôi nghĩ rằng cuối cùng và chỉ dừng lại bằng cách sử dụng các lớp học một phần. Nó chỉ hoạt động sau đó. Tuy nhiên, vì DLL của tôi thực sự được biên dịch bằng trình biên dịch dòng lệnh csc.exe chứ không phải VS.NET, tôi thấy rằng việc thay đổi thứ tự của các tệp trong dòng lệnh đã ảnh hưởng đến thứ tự mà giao diện đã được tạo cho lớp một phần. Nhưng chỉ cần không sử dụng các lớp học một phần là giải pháp đơn giản hơn. – RoboJ1M

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