Возвращение IntPtr в IUnknown для COM - PullRequest
0 голосов
/ 06 октября 2018

У меня под рукой IntPtr до IUnknown управляемого объекта, где управляемый объект находится в другом домене приложения.Это означает, что указатель на это CCW.Я хотел бы разработать сигнатуру метода, которая возвращает это должным образом другим клиентам COM, таким как классический ASP.Что-то вроде этого:

[return: MarshalAs(UnmanagedType.IUnknown)]
public IntPtr Resolve(string typeName);

Однако это не работает..NET не достаточно умен, чтобы делать правильные вещи здесь.Метод выглядит как фактическое целочисленное значение.

Я не хочу возвращать object, поскольку я не хочу разрешать фактический управляемый экземпляр, так как я не хочу, чтобы он пытался загрузитьсвязанная управляемая сборка в этом конкретном AppDomain.Это IntPtr связано с управляемым объектом, который поступает из другого AppDomain.

[EDIT]

Некоторое дополнительное объяснение: я пытаюсь получить управляемые объекты COM из ASP.Net, которые находятся в AppDomain, отличном от домена по умолчанию.Обычно, когда вы делаете CreateObject("managedobject"), вы в конечном итоге создаете экземпляр в рамках AppDomain процесса по умолчанию.Вместо этого я предоставляю прокси для разрешения объектов из другого домена приложений.Таким образом, это означает, что мой прокси находится в домене по умолчанию, но его метод Resolve возвращает управляемый объект из другого домена и возвращает его обратно вызывающему COM-клиенту.

Полный вариант использования: у меня естьклассический ASP и ASP.Net в одном процессе.Я хочу разрешить управляемые объекты .NET, которые находятся в одном домене приложений одного и того же сайта, который объединяет их.ASP.Net генерирует домен приложений для каждого сайта.Однако ASP, будучи неуправляемым, ничего не знает об этом.Однако это управляемый конвейер IIS, поэтому он должен работать.

Дополнительное примечание: у меня на сайте ASP.Net имеется контейнер Autofac, из которого я хочу разрешить объекты.

Да, я пытаюсь использовать Autofac и DI из классического ASP.Сумасшедшие времена!

Оказывается, я заставил его работать:

    /// <summary>
    /// Resolves an object from the container.
    /// </summary>
    /// <param name="typeName"></param>
    /// <returns></returns>
    [return: MarshalAs(UnmanagedType.IUnknown)]
    public object Resolve(string typeName)
    {
        var ptr = (GetProxy() ?? GetGlobalProxy())?.Resolve(typeName) ?? IntPtr.Zero;
        if (ptr == IntPtr.Zero)
            return null;

        // resolve to RCW, which .Net can marshal correctly
        var obj = Marshal.GetObjectForIUnknown(ptr);
        Marshal.Release(ptr);

        return obj;
    }

Это сгенерировало RCW для удаленного CCW.Который может быть помечен как IUnknown правильно.Это технически ненужный объект, я думаю, поскольку исходный COM-объект может правильно получать эти вызовы, и нам фактически не нужно передавать его с RCW.Но это делает маршаллера счастливым.

Все еще ищет лучшие решения.

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

<object runat="server" scope="Application" id="ComponentContext" progid="Cogito.Autofac.Asp.ComponentContextProxy"></object>

С последующим Set obj = ComponentContext.Resolve("Cogito.Autofac.Asp.Sample.Objects.ResolvableObject, Cogito.Autofac.Asp.Sample.Objects") на странице ASP.И это разрешает объект из Autofac.Красивые.

...