Почему делает доступ к COM-объекту от.NET, не проходя класс Interop, иногда работают?

При взаимодействии через интерфейс с COM-объектом из кода.NET VS создает interop DLL с interop классами.

Пример:

У Вас есть foo.dll реализации Нечто библиотеки COM, которое включает реализацию COM-интерфейса "IBar". Вы добавляете ссылку на foo.dll к проекту.NET. в / мусорном ведре Вы будете видеть Interop.FooLib.dll. В Обозревателе объектов Вы будете видеть Interop. FooLib, под которым Вы будете видеть FooLib, под которым Вы будете видеть BarClass, под которым Вы будете видеть Базовые типы под той Панелью и IBar.

В Вашем коде.NET, при объявлении переменной, можно ввести FooLib, и intellisense даст Вам опции или Панели или BarClass ().

Из того, что я понял, это действительно не имеет значения, который Вы используете в объявлении переменной, но это очень имеет значение, который Вы использовали для его конструктора.

Таким образом, оба из них должны работать:

FooLib.BarClass theBar = new FooLib.BarClass();
FooLib.Bar theBar = new FooLib.BarClass();

Но это не должно работать:

FooLib.Bar theBar = new FooLib.Bar();

Вот проблема. Мы просто разыскали нечетную ошибку, где код, который работал на некоторых клиентов, и работал в наших средах разработки и тестовых средах, не работал на одном сайте для клиентов, выпущенном, чтобы быть программистом, использующим Панель () конструктор.

Так, кто-либо может объяснить точно, что различие между этими двумя конструкторами, Панель (), и BarClass ()?

Кто-либо может объяснить, почему Панель () конструктор, кажется, работает, иногда?

Кто-либо может предоставить метод для обеспечения, что никто по ошибке не вызывает неправильных конструкторов, не читая каждую строку кода?

- ДОБАВЛЕННЫЙ-

Было предложено, чтобы проблема была в нашей реализации COM. Это - то, что мы делаем:

IDL:

[
    object,
    uuid(...),
    dual,
    helpstring("IBar Interface"),
    pointer_default(unique),
    nonextensible
]
interface IBar : IDispatch
{
    [id(1), helpstring("method barify")] 
        HRESULT barify([out, retval] VARIANT_BOOL *rVal);
    // ...
};
// ...
[
    uuid(...),
    version(1.0),
    helpstring("Foo 1.0 Type Library")
]
library FooLib
{
    importlib("stdole32.tlb");
    importlib("stdole2.tlb");
    // ...
    [
        uuid(...),
        helpstring("Bar Class")
    ]
    coclass Bar
    {
        [default] interface IBar;
    };
    // ...
};

Реализация:

class ATL_NO_VTABLE CBar : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CBar, &CLSID_Bar>,
    public IDispatchImpl<IBar, &IID_IBar, &LIBID_FooLib>,
    public ISupportErrorInfoImpl <&IID_IBar>
{
public:
    CBar();

    DECLARE_REGISTRY_RESOURCEID(IDR_BAR)

    DECLARE_PROTECT_FINAL_CONSTRUCT()

    BEGIN_COM_MAP(CBar)
        COM_INTERFACE_ENTRY(IBar)
        COM_INTERFACE_ENTRY(IDispatch)
        COM_INTERFACE_ENTRY(ISupportErrorInfo)
    END_COM_MAP()

    // ...
};

- ДОБАВЛЕННЫЙ ПОЗЖЕ-

Декомпилируйтесь* через Отражатель.NET:

[ComImport, CoClass(typeof(BarClass)), Guid("...")]
public interface Bar : IBar
{
}

*Я не забочусь, что Отражатель, UI называет это дизассемблированием - если это производит HLL, это - декомпиляция.

11
задан Jeff Dege 17 June 2010 в 20:10
поделиться

3 ответа

Отличный вопрос. Многие люди удивлены, что это вообще работает, потому что Bar - это интерфейс, и вы, конечно же, не сможете создать новый экземпляр интерфейса! Но хотя я не могу найти каких-либо особенностей реализации, я помню, как читал в книге Адама Натана по COM-взаимодействию, что C # делает специальное исключение для COM-интерфейсов, помеченных CoClassAttribute, и вместо этого превращает вызов в экземпляр кокласса.

Но я не знаю, почему это иногда срабатывает, а иногда нет.

2
ответ дан 3 December 2019 в 12:17
поделиться

Читали ли вы обсуждение в этом вопросе? Там обсуждается именно этот вопрос, я думаю.

0
ответ дан 3 December 2019 в 12:17
поделиться

Конструктор Bar () в принципе должен явно возвращать интерфейс, а не объект класса. Я не могу понять, как .NET поддерживает создание интерфейса !?

В любом случае вы можете щелкнуть конструктор Bar () и нажать Shift-F12. Это покажет вам где-нибудь еще в коде, где используется этот конструктор. Я не могу придумать способ предотвратить случайный вызов этого конструктора пользователем.

0
ответ дан 3 December 2019 в 12:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: