将IntPtr返回给COM的IUnknown

时间:2018-10-06 16:33:01

标签: .net com interop

我手头有一个IntPtr到受管理对象IUnknown的位置,其中受管理对象位于另一个AppDomain中。这意味着指向它的CCW。我想设计一种方法签名,以将其正确返回给其他COM客户端,例如经典ASP。像这样的东西:

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

但是,这不起作用。 .NET不够聪明,无法在此处执行正确的操作。该方法作为实际的整数值出现。

我不想返回object,因为我不想解析实际的托管实例,因为我不想让它尝试在此特定的AppDomain中加载关联的托管程序集。该IntPtr与来自不同AppDomain的托管对象相关联。

[编辑]

一些其他说明:我正在尝试处理从ASP.Net获取的托管COM对象,该对象位于默认域之外的AppDomain中。通常,当您执行CreateObject("managedobject")时,最终会在流程的默认AppDomain内创建实例。相反,我提供了一个代理来解析来自另一个AppDomain的对象。因此,这意味着我的代理驻留在默认域中,但是它的Resolve方法从另一个域返回一个托管对象,并将其返回给调用COM客户端。

完整用例:我在同一过程中拥有经典的ASP和ASP.Net。我想解析驻留在共同托管两个站点的同一AppDomain中的托管.NET对象。 ASP.Net为每个站点生成一个AppDomain。但是,不受管理的ASP对此一无所知。但是,这是一个托管的IIS管道,因此应该可以使用。

附加说明:我想在ASP.Net站点中拥有一个要解析对象的Autofac容器。

是的,我正在尝试从经典ASP中使用Autofac和DI。疯狂的时代!

结果证明我可以使用它

    /// <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;
    }

这为远程CCW生成了RCW。可以将其正确地编组为IUnknown。从技术上讲,我认为这是不必要的对象,因为原始的COM对象可以正确接收这些调用,并且我们实际上不需要在RCW前面添加它。但是,这使编组人员感到高兴。

仍在寻找更好的解决方案。

因此,我的用例可行。在Classic 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解析对象。美丽。

0 个答案:

没有答案