.Net-объект не поддерживает IDispatch???
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 13.12.06 07:18
Оценка:
Добрый день!

Народ, в MSDN черным по белому написано: COM callable wrapper всегда эмулирует интерфейсы IDispatch, IUnknown и еще несколько, типа ITypeInfo. Создаю в сборке экземпляр UserControl, из клиентского Win32-приложения получаю его через такой интерфейс:
    [ComVisible(true)]
    [Guid("4542FE0B-AA92-4D62-9167-E36B07922E94")]
    public interface IXView
    {
        [return: MarshalAs(UnmanagedType.IUnknown)]
        object GetOleControl();
    }


Но потом, уже в Win32, результат почему-то не приводится к IDispatch (дает ошибку Ole error: "The specified cast is not valid"), та же фигня и с ITypeInfo. Притом, что сам метод GetOleControl завершается нормально.

Кто виноват и что делать?

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re: .Net-объект не поддерживает IDispatch???
От: DuШes  
Дата: 13.12.06 07:36
Оценка:
[msdn]


The following code fragment demonstrates how to declare in managed source code an unmanaged interface implemented by a COM component. The System.Runtime.InteropServices.ComImportAttribute prevents the IMyStorage interface from being exported back for use by COM. (COM clients should use the existing COM component directly.) In this example, MarshalAsAttribute specifies serveral UnmanagedType members, which represent the types used by the original COM interface.


using System;
using System.Runtime.InteropServices;

namespace MyModule
{
    // If you do not have a type library for an interface
    // you can redeclare it using ComImportAttribute.

    // This is how the interface would look in an idl file.

    //[
    //object,
    //uuid("73EB4AF8-BE9C-4b49-B3A4-24F4FF657B26"),
    //dual,    helpstring("IMyStorage Interface"),
    //pointer_default(unique)
    //]
    //interface IMyStorage : IDispatch
    //{
    //    [id(1)]
    //    HRESULT GetItem([in] BSTR bstrName, [out, retval] IDispatch ** ppItem);
    //    [id(2)]
    //    HRESULT GetItems([in] BSTR bstrLocation, [out] SAFEARRAY(VARIANT)* pItems);
    //    [id(3)]
    //    HRESULT GetItemDescriptions([in] BSTR bstrLocation, [out] SAFEARRAY(VARIANT) ** ppItems);
    //    [id(4), propget]
    //    HRESULT get_IsEmpty([out, retval] BOOL * pfEmpty);
    //};

    // This is the managed declaration.

    [ComImport]
    [Guid("73EB4AF8-BE9C-4b49-B3A4-24F4FF657B26")]
    public interface IMyStorage  
    {
        [DispId(1)]
        [return : MarshalAs( UnmanagedType.Interface )]
        Object GetItem( [In, MarshalAs( UnmanagedType.BStr )] String bstrName );

        [DispId(2)]
        void GetItems( [In, MarshalAs( UnmanagedType.BStr )] String bstrLocation, 
            [Out, MarshalAs( UnmanagedType.SafeArray, 
                      SafeArraySubType = VarEnum.VT_VARIANT )] out Object[] Items );
                
                
        [DispId(3)]
        void GetItemDescriptions( [In] String bstrLocation, 
            [In, Out, MarshalAs( UnmanagedType.SafeArray )] ref Object[] varDescriptions );

        bool IsEmpty 
        {
            [DispId(4)]
            [return : MarshalAs( UnmanagedType.VariantBool )]
            get;
        }
    }
}

Re[2]: .Net-объект не поддерживает IDispatch???
От: DuШes  
Дата: 13.12.06 07:38
Оценка:
вдогонку
смотри InterfaceType, в частности
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
Re[3]: .Net-объект не поддерживает IDispatch???
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 13.12.06 08:21
Оценка:
Здравствуйте, DuШes, Вы писали:

И что мне этот фрагмент дает?

Моя задача в том, чтобы передать наружу в виде какого-либо интерфейса объект, но так, чтобы он обязательно поддерживал IDispatch. Мне не нужно, чтобы IXView реализовывал IDispatch. Мне нужно, чтобы метод IXView передал наружу UserControl в виде к-либо интерфейса, но так, чтобы этот интерфейс можно было привести к IDispatch.

DШ>вдогонку

DШ>смотри InterfaceType, в частности
DШ>[InterfaceType(ComInterfaceType.InterfaceIsDual)]
Опять-таки, на какой интерфейс мне наклеить этот атрибут? Если я возвращаю object... Кстати, я уже пробовал и возвращать какой-то другой интерфейс, ставить на него дуальность — и все равно приведение не работает! Этого я уже вообще не понимаю:

[c#]
[ComVisible(true)]
[Guid("4542FE0B-AA92-4D62-9167-E36B07922E94")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IXFrame
{
}

.....

public IXFrame GetOleControl() //потом возвращаемый результат в Win32 привожу к IDispatch, облом
{
return (IXFrame)m_frame;
}

[c#]

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[4]: .Net-объект не поддерживает IDispatch???
От: DuШes  
Дата: 13.12.06 09:46
Оценка:
Здравствуйте, Slicer [Mirkwood], Вы писали:

SM> public IXFrame GetOleControl() //потом возвращаемый результат в Win32 привожу к IDispatch, облом

SM> {
SM> return (IXFrame)m_frame;
SM> }


m_frame — наследник от UserControl — если да, то все должно работать, ибо

[ComVisible(true), 
ClassInterface(ClassInterfaceType.AutoDispatch)]
public class UserControl : ContainerControl


у самого метода как я понимаю нужно выставить
[DispId(1)][return : MarshalAs( UnmanagedType.Interface )]...
хотя, не нужно было маршаллить .net windows forms controls наружу, не сталкивался
Re: .Net-объект не поддерживает IDispatch???
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 13.12.06 11:04
Оценка:
Сорри, сам дурак. Вот так два дела одновременно делать -) Просто мой возвращаемый контрол был потомком UserControl =) И был не ком-визибл...

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.