Предоставление свойств индексатора как COM - PullRequest
2 голосов
/ 23 июня 2011

У меня в существующем COM-интерфейсе.Я не хочу создавать сборку .net, которая представляет новый интерфейс как COM (с новым GUID), но структура интерфейса должна быть такой же.

Как создать класс .net(C #), который выставляет этот интерфейс?

[
  odl,
  uuid(1ED4C594-DDD7-402F-90DE-7F85D65560C4),
  hidden,
  oleautomation
]
interface _IFlashPhase : IUnknown {

    [propget]
    HRESULT _stdcall ComponentName(
                    [in] short i, 
                    [out, retval] BSTR* pVal);
    [propput]
    HRESULT _stdcall ComponentName(
                    [in] short i, 
                    [in] BSTR pVal);
    [propget]
    HRESULT _stdcall ComponentMolePercent(
                    [in] short i, 
                    [out, retval] double* pVal);
    [propput]
    HRESULT _stdcall ComponentMolePercent(
                    [in] short i, 
                    [in] double pVal);
    [propget]
    HRESULT _stdcall ComponentFugacity(
                    [in] short i, 
                    [out, retval] double* pVal);
    [propput]
    HRESULT _stdcall ComponentFugacity(
                    [in] short i, 
                    [in] double pVal);

};

1 Ответ

7 голосов
/ 23 июня 2011

Ваш IDL недействителен, интерфейс с атрибутом [oleautomation] должен быть производным от IDispatch, а не IUnknown.Я дам правильные объявления и подсказку, где вам нужно изменить их, чтобы получить ваши.

Вы не можете объявить индексированные свойства в C #, команда C # отказывается их реализовывать.В версии 4 есть поддержка индексированных свойств, которые объявлены в библиотеке типов COM, но по-прежнему не позволяют объявлять их самостоятельно.Обходной путь должен использовать язык VB.NET, он не сомневается в этом.Добавьте проект библиотеки классов VB.NET в свое решение.Сделайте так, чтобы это выглядело примерно так:

Imports System.Runtime.InteropServices

Namespace Mumble

    <ComVisible(True)> _
    <Guid("2352FDD4-F7C9-443a-BC3F-3EE230EF6C1B")> _
    <InterfaceType(ComInterfaceType.InterfaceIsDual)> _
    Public Interface IExample
        <DispId(0)> _
        Property Indexer(ByVal index As Integer) As Integer
        <DispId(1)> _
        Property SomeProperty(ByVal index As Integer) As String
    End Interface

End Namespace

Обратите внимание на использование <DispId>, dispid 0 особенный, это свойство по умолчанию интерфейса.Это соответствует индексатору на языке C #.

Все, что вам нужно для VB.NET - это объявление, вы все равно можете написать реализацию интерфейса на языке C #.Проект + Добавить ссылку, вкладка Проекты и выберите проект VB.NET.Сделайте так, чтобы это выглядело примерно так:

using System;
using System.Runtime.InteropServices;

namespace Mumble {
    [ComVisible(true)]
    [Guid("8B72CE6C-511F-456e-B71B-ED3B3A09A03C")]
    [ClassInterface(ClassInterfaceType.None)]
    public class Implementation : ClassLibrary2.Mumble.IExample {
        public int get_Indexer(int index) {
            return index;
        }
        public void set_Indexer(int index, int Value) {
        }

        public string get_SomeProperty(int index) {
            return index.ToString();
        }

        public void set_SomeProperty(int index, string Value) {
        }
    }
}

Вам необходимо запустить Tlbexp.exe на и сборки VB.NET и C # для генерации библиотек типов.В C # one с реализацией входит VB.NET.

Чтобы интерфейс получался из IUnknown вместо IDispatch, отредактируйте объявление интерфейса.Удалите атрибуты DispId и используйте ComInterfaceType.InterfaceIsUnknown

...