static Func <IntPtr, object> getFactory(Type tInterface)
        {
            Func <IntPtr, object> factory = null;

            lock ( syncRoot )
            {
                if (factories.TryGetValue(tInterface, out factory))
                {
                    return(factory);
                }
                Func <IntPtr, object> newProxy = Proxy.build(tInterface);
                factory = ( IntPtr pNative ) =>
                {
                    RuntimeClass rc = LiveObjectsCache.nativeLookup(pNative);
                    if (null != rc)
                    {
                        return(rc);
                    }
                    ManagedObject mo = LiveObjectsCache.managedLookup(pNative);
                    if (null != mo)
                    {
                        return(mo.managed);
                    }
                    return(newProxy(pNative));
                };
                factories.Add(tInterface, factory);
                return(factory);
            }
        }
Esempio n. 2
0
        /// <summary>Create a factory which supports two-way marshaling.</summary>
        static Func <IntPtr, object> createTwoWayFactory(Type tInterface)
        {
            Func <IntPtr, object> newProxy = Proxy.build(tInterface);

            return(( IntPtr pNative ) =>
            {
                if (pNative == IntPtr.Zero)
                {
                    return null;
                }

                RuntimeClass rc = Cache.Native.lookup(pNative, tInterface);
                if (null != rc)
                {
                    return rc;
                }

                ManagedObject mo = Cache.Managed.lookup(pNative);
                if (null != mo)
                {
                    return mo.managed;
                }

                return newProxy(pNative);
            });
        }
        public static void nativeAdd(IntPtr p, RuntimeClass rc)
        {
            Debug.Assert(p != IntPtr.Zero);

            lock ( syncRoot )
            {
                Debug.Assert(!native.ContainsKey(p));
                native.Add(p, new WeakReference <RuntimeClass>(rc));
            }
        }
        static Func <object, bool, IntPtr> getFactory <I>() where I : class
        {
            Type tInterface = typeof(I);
            Func <object, bool, IntPtr> result;

            lock ( syncRoot )
            {
                if (cache.TryGetValue(tInterface, out result))
                {
                    return(result);
                }

                Guid iid = ReflectionUtils.checkInterface(tInterface);
                // The builder gets captured by the lambda.
                // This is what we want, the constructor takes noticeable time, the code outside lambda runs once per interface type, the code inside lambda runs once per object instance.
                InterfaceBuilder builder = new InterfaceBuilder(tInterface);

                result = (object obj, bool addRef) =>
                {
                    if (null == obj)
                    {
                        // Marshalling null
                        return(IntPtr.Zero);
                    }
                    Debug.Assert(obj is I);

                    RuntimeClass rc = obj as RuntimeClass;
                    if (null != rc)
                    {
                        // That .NET object is not actually managed, it's a wrapper around C++ implemented COM interface.
                        if (rc.iid == iid)
                        {
                            // It wraps around the same interface
                            if (addRef)
                            {
                                rc.addRef();
                            }
                            return(rc.nativePointer);
                        }

                        // It wraps around different interface. Call QueryInterface on the native object.
                        return(rc.queryInterface(iid, addRef));
                    }

                    // It could be the same managed object is reused across native calls. If that's the case, the cache already contains the native pointer.
                    I      managed = (I)obj;
                    IntPtr?wrapped = WrappersCache <I> .lookup(managed);

                    if (wrapped.HasValue)
                    {
                        return(wrapped.Value);
                    }

                    Delegate[]    delegates = builder.compile(managed);
                    ManagedObject wrapper   = new ManagedObject(managed, iid, delegates);
                    WrappersCache <I> .add(managed, wrapper);

                    if (addRef)
                    {
                        wrapper.callAddRef();
                    }
                    return(wrapper.address);
                };

                cache.Add(tInterface, result);
                return(result);
            }
        }