Как объявить классический интерфейс COM IBindCtx в C#?

В настоящее время я ковыряюсь в C# и COM интерфейсах. Документация COM в C# редкая, потому что C# появился после COM (возможно, мы в SO можем это исправить). Я обнаружил, что компилятор C# может выдавать информативные сообщения об ошибках. Можно прочитать синтаксическую версию C# сигнатур метода из сообщений об ошибках, а затем добавить в свой класс. Это работает для IAdviseSink, но не работает для IBindCtx.

Я получаю ошибку для последнего метода RevokeObjectParam(string a) синтаксис в C++ HRESULT RevokeObjectParam( [in] LPOLESTR pszKey ); а также LPOLESTR 2-байтовая строка с нулевым символом в конце, поэтому [MarshalAs(UnmanagedType.LPWStr)] должно сработать. Но это не так, я получаю сообщения об ошибках

     * Class1.cs(25,14,25,40): error CS0539: 'IBindCtx.RevokeObjectParam' in explicit interface declaration is not a member of interface
     * Class1.cs(6,18,6,24): error CS0535: 'ComInterfacesInCSharp.Class1' does not implement interface member 'System.Runtime.InteropServices.ComTypes.IBindCtx.RevokeObjectParam(string)'

Так как же изменить подпись этого метода, чтобы исправить, пожалуйста? Полный код, который можно скопировать в Visual Studio, приведен ниже (создайте проект библиотеки классов).

using System.Runtime.InteropServices.ComTypes;
using System.Runtime.InteropServices;

namespace ComInterfacesInCSharp
{
    public class Class1 : System.Runtime.InteropServices.ComTypes.IBindCtx 
    {
        void IBindCtx.RegisterObjectBound(object obj) { }
        void IBindCtx.RevokeObjectBound(object obj) { }
        void IBindCtx.ReleaseBoundObjects() { }
        void IBindCtx.SetBindOptions(ref System.Runtime.InteropServices.ComTypes.BIND_OPTS opts) { }
        void IBindCtx.GetBindOptions(ref System.Runtime.InteropServices.ComTypes.BIND_OPTS opts) { }
        void IBindCtx.GetRunningObjectTable(out System.Runtime.InteropServices.ComTypes.IRunningObjectTable tab) { }
        void IBindCtx.RegisterObjectParam(string s, object obj) { }
        void IBindCtx.GetObjectParam(string s, out object obj) { }
        void IBindCtx.EnumObjectParam(out System.Runtime.InteropServices.ComTypes.IEnumString enumString) { }

        /* Problem here https://msdn.microsoft.com/en-us/library/windows/desktop/ms693771(v=vs.85).aspx
         * C++ Syntax is 
         * HRESULT RevokeObjectParam( [in] LPOLESTR pszKey );
         * LPOLESTR is a null terminated 2 byte based string so UnmanagedType.LPWStr ought to work
         * 
         */
        //void IBindCtx.RevokeObjectParam(string a) { }
        void IBindCtx.RevokeObjectParam([MarshalAs(UnmanagedType.LPWStr)] string a) { }

        /*
         * Compile errors are
         * Class1.cs(25,14,25,40): error CS0539: 'IBindCtx.RevokeObjectParam' in explicit interface declaration is not a member of interface
         * Class1.cs(6,18,6,24): error CS0535: 'ComInterfacesInCSharp.Class1' does not implement interface member 'System.Runtime.InteropServices.ComTypes.IBindCtx.RevokeObjectParam(string)'
         */
    }
}

Кстати, если у вас есть веб-ресурс, детализирующий эти интерфейсы в C#, то это было бы чудесно!

1 ответ

Решение

ссылка, которую вы дали, превосходна! Это отвечает на мой вопрос, какой была правильная подпись метода. Теперь я определенно от Microsoft.

Хотя многие определения исходного кода можно найти на веб-узле Microsoft Reference Source, это не единственный вариант обнаружения подписи для метода, определенного в сборке.

Научитесь использовать обозреватель объектов Visual Studio. Откройте Меню-> Обозреватель объектов (или нажмите клавишу F2).

В вашем конкретном случае реализации интерфейса вы можете сделать так, чтобы Visual Studio автоматически реализовал интерфейс для вас. Щелкните правой кнопкой мыши на названии интерфейса и выберите "Реализовать интерфейс".

Другие вопросы по тегам