public RpcObjectProxyFactory GenerateObjectProxyFactory <TService>(
            IReadOnlyCollection <string>?implementedServices,
            IReadOnlyDictionary <string, ImmutableArray <Type> >?knownServiceTypes)
            where TService : class
        {
            lock (this.syncRoot)
            {
                var serviceInterfaces = GetAllServices <TService>(implementedServices, knownServiceTypes);
                var key = new HashSetKey <Type>(serviceInterfaces.Select(s => s.Type));

                // If a proxy with the same set of service interfaces has been generated before
                // let's reuse that one.
                if (this.generatedFactories.TryGetValue(key, out var currFactory))
                {
                    // TODO: Should maybe look for a factory which has a superset of implemented interfaces?
                    return((RpcObjectProxyFactory)currFactory);
                }

                var(moduleBuilder, definedProxyTypes) = CreateModuleBuilder();

                var proxyTypeBuilder = new RpcServiceProxyBuilder <TRpcProxy, TMethodDef>(
                    serviceInterfaces,
                    moduleBuilder, definedProxyTypes);
                (Func <TProxyArgs, TMethodDef[], RpcProxyBase> proxyCreator, TMethodDef[] proxyMethodDefs)
                    = proxyTypeBuilder.BuildObjectProxyFactory <TProxyArgs>();

                RpcObjectProxyFactory newFactory = this.CreateProxyFactory(proxyCreator, implementedServices, proxyMethodDefs);

                this.generatedFactories.Add(key, newFactory);

                return(newFactory);
            }
        }
Example #2
0
        private TService GetServiceInstanceCore <TService>(
            RpcObjectId refObjectId,
            IReadOnlyCollection <string>?implementedServices,
            SynchronizationContext?syncContext) where TService : class
        {
            lock (this.SyncRoot)
            {
                if (this.serviceInstances.TryGetValue(refObjectId, out var servicesList))
                {
                    foreach (var wService in servicesList)
                    {
                        if (wService.TryGetTarget(out var proxyBase) &&
                            proxyBase is TService service &&
                            proxyBase.SyncContext == syncContext &&
                            proxyBase.ImplementsServices(implementedServices))
                        {
                            return(service);
                        }
                    }
                }
            }

            RpcObjectProxyFactory serviceProxyCreator
                = this.proxyGenerator.GenerateObjectProxyFactory <TService>(implementedServices, this.Options.KnownServiceTypesDictionary);

            lock (this.SyncRoot)
            {
                if (this.serviceInstances.TryGetValue(refObjectId, out var servicesList))
                {
                    foreach (var wService in servicesList)
                    {
                        if (wService.TryGetTarget(out var proxyBase) &&
                            proxyBase is TService service &&
                            proxyBase.SyncContext == syncContext &&
                            proxyBase.ImplementsServices(implementedServices))
                        {
                            return(service);
                        }
                    }
                }
                else
                {
                    servicesList = new List <WeakReference <RpcProxyBase> >();
                    this.serviceInstances.Add(refObjectId, servicesList);
                }

                var serviceInstance = serviceProxyCreator(refObjectId, this, syncContext);
                servicesList.Add(new WeakReference <RpcProxyBase>(serviceInstance));

                return((TService)(object)serviceInstance);
            }
        }