/// <summary>
        /// Returns the <see cref="GrainType"/> which supports the provided <see cref="GrainInterfaceType"/> and which has an implementing type name beginning with the provided prefix string.
        /// </summary>
        public GrainType GetGrainType(GrainInterfaceType interfaceType, string prefix)
        {
            if (string.IsNullOrWhiteSpace(prefix))
            {
                return(GetGrainType(interfaceType));
            }

            GrainType result = default;

            GrainInterfaceType lookupType;

            if (GenericGrainInterfaceType.TryParse(interfaceType, out var genericInterface))
            {
                lookupType = genericInterface.GetGenericGrainType().Value;
            }
            else
            {
                lookupType = interfaceType;
            }

            var cache = GetCache();

            if (cache.Map.TryGetValue(lookupType, out var entry))
            {
                var hasCandidate = false;
                foreach (var impl in entry.Implementations)
                {
                    if (impl.Prefix.StartsWith(prefix, StringComparison.Ordinal))
                    {
                        if (impl.Prefix.Length == prefix.Length)
                        {
                            // Exact matches take precedence
                            result = impl.GrainType;
                            break;
                        }

                        if (hasCandidate)
                        {
                            var candidates = string.Join(", ", entry.Implementations.Select(i => $"{i.GrainType} ({i.Prefix})"));
                            throw new ArgumentException($"Unable to identify a single appropriate grain type for interface {interfaceType} with implementation prefix \"{prefix}\". Candidates: {candidates}");
                        }

                        result       = impl.GrainType;
                        hasCandidate = true;
                    }
                }
            }

            if (result.IsDefault)
            {
                throw new ArgumentException($"Could not find an implementation matching prefix \"{prefix}\" for interface {interfaceType}");
            }

            if (GenericGrainType.TryParse(result, out var genericGrainType) && !genericGrainType.IsConstructed)
            {
                result = genericGrainType.GrainType.GetConstructed(genericInterface.Value);
            }

            return(result);
        }
        /// <summary>
        /// Returns a <see cref="GrainType"/> which implements the provided <see cref="GrainInterfaceType"/>.
        /// </summary>
        public GrainType GetGrainType(GrainInterfaceType interfaceType)
        {
            GrainType result = default;
            var       cache  = GetCache();

            if (cache.Map.TryGetValue(interfaceType, out var entry))
            {
                if (!entry.PrimaryImplementation.IsDefault)
                {
                    result = entry.PrimaryImplementation;
                }
                else if (entry.Implementations.Count == 1)
                {
                    result = entry.Implementations[0].GrainType;
                }
                else if (entry.Implementations.Count > 1)
                {
                    var candidates = string.Join(", ", entry.Implementations.Select(i => $"{i.GrainType} ({i.Prefix})"));
                    throw new ArgumentException($"Unable to identify a single appropriate grain type for interface {interfaceType}. Candidates: {candidates}");
                }
                else
                {
                    // No implementations
                }
            }
            else if (_genericMapping.TryGetValue(interfaceType, out result))
            {
            }
            else if (GenericGrainInterfaceType.TryParse(interfaceType, out var genericInterface))
            {
                var unconstructedInterface = genericInterface.GetGenericGrainType();
                var unconstructed          = GetGrainType(unconstructedInterface.Value);
                if (GenericGrainType.TryParse(unconstructed, out var genericGrainType))
                {
                    if (genericGrainType.IsConstructed)
                    {
                        result = genericGrainType.GrainType;
                    }
                    else
                    {
                        result = genericGrainType.GrainType.GetConstructed(genericInterface.Value);
                    }
                }
                else
                {
                    result = unconstructed;
                }
                _genericMapping[interfaceType] = result;
            }

            if (result.IsDefault)
            {
                throw new ArgumentException($"Could not find an implementation for interface {interfaceType}");
            }

            return(result);
        }
Esempio n. 3
0
        private void CheckIfIsExistingInterface(GrainInterfaceType interfaceType)
        {
            GrainInterfaceType lookupId;

            if (GenericGrainInterfaceType.TryParse(interfaceType, out var generic))
            {
                lookupId = generic.Value;
            }
            else
            {
                lookupId = interfaceType;
            }

            if (!this.siloManifest.Interfaces.TryGetValue(lookupId, out _))
            {
                throw new ArgumentException($"Interface '{interfaceType} not found", nameof(interfaceType));
            }
        }
        public ushort GetLocalVersion(GrainInterfaceType interfaceType)
        {
            if (_localVersions.TryGetValue(interfaceType, out var result))
            {
                return(result);
            }

            if (_genericInterfaceMapping.TryGetValue(interfaceType, out var genericInterfaceId))
            {
                return(GetLocalVersion(genericInterfaceId));
            }

            if (GenericGrainInterfaceType.TryParse(interfaceType, out var generic) && generic.IsConstructed)
            {
                var genericId = _genericInterfaceMapping[interfaceType] = generic.GetGenericGrainType().Value;
                return(GetLocalVersion(genericId));
            }

            return(0);
        }
        public (MajorMinorVersion Version, SiloAddress[] Result) GetSupportedSilos(GrainInterfaceType interfaceType, ushort version)
        {
            var cache = GetCache();

            if (cache.SupportedSilosByInterface.TryGetValue((interfaceType, version), out var result))
            {
                return(cache.Version, result);
            }

            if (_genericInterfaceMapping.TryGetValue(interfaceType, out var genericInterfaceId))
            {
                return(GetSupportedSilos(genericInterfaceId, version));
            }

            if (GenericGrainInterfaceType.TryParse(interfaceType, out var generic) && generic.IsConstructed)
            {
                var genericId = _genericInterfaceMapping[interfaceType] = generic.GetGenericGrainType().Value;
                return(GetSupportedSilos(genericId, version));
            }

            // No supported silos for this version.
            return(cache.Version, Array.Empty <SiloAddress>());
        }
        public (MajorMinorVersion Version, ushort[] Result) GetAvailableVersions(GrainInterfaceType interfaceType)
        {
            var cache = GetCache();

            if (cache.AvailableVersions.TryGetValue(interfaceType, out var result))
            {
                return(cache.Version, result);
            }

            if (_genericInterfaceMapping.TryGetValue(interfaceType, out var genericInterfaceId))
            {
                return(GetAvailableVersions(genericInterfaceId));
            }

            if (GenericGrainInterfaceType.TryParse(interfaceType, out var generic) && generic.IsConstructed)
            {
                var genericId = _genericInterfaceMapping[interfaceType] = generic.GetGenericGrainType().Value;
                return(GetAvailableVersions(genericId));
            }

            // No versions available.
            return(cache.Version, Array.Empty <ushort>());
        }