public static TypeReferenceBuilder ToTypeReference(
            this ITypeDescriptor typeReferenceDescriptor,
            TypeReferenceBuilder?builder = null)
        {
            TypeReferenceBuilder actualBuilder = builder ?? TypeReferenceBuilder.New();

            if (typeReferenceDescriptor is NonNullTypeDescriptor n)
            {
                typeReferenceDescriptor = n.InnerType;
            }
            else
            {
                actualBuilder.SetIsNullable(true);
            }

            return(typeReferenceDescriptor switch
            {
                ListTypeDescriptor list =>
                ToTypeReference(list.InnerType, actualBuilder.SetListType()),

                EnumTypeDescriptor @enum =>
                actualBuilder.SetName(@enum.RuntimeType.ToString()),

                ILeafTypeDescriptor leaf =>
                actualBuilder.SetName(leaf.RuntimeType.ToString()),

                INamedTypeDescriptor named =>
                actualBuilder.SetName(named.RuntimeType.ToString()),

                _ => throw new ArgumentOutOfRangeException(nameof(typeReferenceDescriptor))
            });
Example #2
0
        public static void Map(ClientModel model, IMapperContext context)
        {
            foreach (OperationModel modelOperation in model.Operations)
            {
                var arguments = modelOperation.Arguments.Select(
                    arg =>
                {
                    NameString typeName = arg.Type.TypeName();

                    INamedTypeDescriptor namedTypeDescriptor =
                        context.Types.Single(type => type.Name.Equals(typeName));

                    return(new PropertyDescriptor(
                               arg.Name,
                               Rewrite(arg.Type, namedTypeDescriptor)));
                })
                                .ToList();

                var resultTypeName = CreateResultRootTypeName(modelOperation.ResultType.Name);

                switch (modelOperation.OperationType)
                {
                case OperationType.Query:
                    context.Register(
                        modelOperation.Name,
                        new QueryOperationDescriptor(
                            modelOperation.Name,
                            context.Types.Single(t => t.RuntimeType.Name.Equals(resultTypeName)),
                            context.Namespace,
                            arguments,
                            modelOperation.Document.ToString()));
                    break;

                case OperationType.Mutation:
                    context.Register(
                        modelOperation.Name,
                        new MutationOperationDescriptor(
                            modelOperation.Name,
                            context.Types.Single(t => t.RuntimeType.Name.Equals(resultTypeName)),
                            context.Namespace,
                            arguments,
                            modelOperation.Document.ToString()));
                    break;

                case OperationType.Subscription:
                    context.Register(
                        modelOperation.Name,
                        new SubscriptionOperationDescriptor(
                            modelOperation.Name,
                            context.Types.Single(t => t.RuntimeType.Name.Equals(resultTypeName)),
                            context.Namespace,
                            arguments,
                            modelOperation.Document.ToString()));
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
        }
Example #3
0
 public ResultFromEntityTypeMapperDescriptor(
     INamedTypeDescriptor entityNamedType,
     INamedTypeDescriptor resultNamedType)
 {
     EntityNamedType = entityNamedType;
     ResultNamedType = resultNamedType;
 }
 public static RuntimeTypeInfo ExtractType(
     this INamedTypeDescriptor descriptor)
 {
     return(descriptor.IsEntityType()
         ? CreateEntityType(descriptor.Name, descriptor.RuntimeType.NamespaceWithoutGlobal)
         : new (descriptor.Name, descriptor.RuntimeType.NamespaceWithoutGlobal));
 }
        /// <summary>
        /// Adds all required deserializers of the given type descriptors properties
        /// </summary>
        private void AddRequiredDeserializeMethods(
            INamedTypeDescriptor namedTypeDescriptor,
            ClassBuilder classBuilder,
            HashSet <string> processed)
        {
            if (namedTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                foreach (var @class in interfaceTypeDescriptor.ImplementedBy)
                {
                    AddRequiredDeserializeMethods(@class, classBuilder, processed);
                }
            }
            else if (namedTypeDescriptor is ComplexTypeDescriptor complexTypeDescriptor)
            {
                foreach (var property in complexTypeDescriptor.Properties)
                {
                    AddDeserializeMethod(
                        property.Type,
                        classBuilder,
                        processed);

                    if (property.Type.NamedType() is INamedTypeDescriptor nt &&
                        !nt.IsLeafType())
                    {
                        AddRequiredDeserializeMethods(nt, classBuilder, processed);
                    }
                }
            }
        }
Example #6
0
 public ResultBuilderDescriptor(
     RuntimeTypeInfo runtimeType,
     INamedTypeDescriptor resultNamedType,
     IReadOnlyCollection <ValueParserDescriptor> valueParsers)
 {
     ResultNamedType = resultNamedType;
     RuntimeType     = runtimeType;
     ValueParsers    = valueParsers;
 }
 public static NameString ExtractMapperName(this INamedTypeDescriptor descriptor)
 {
     return(descriptor.Kind == TypeKind.EntityType
         ? CreateEntityMapperName(
                descriptor.RuntimeType.Name,
                descriptor.Name)
         : CreateDataMapperName(
                descriptor.RuntimeType.Name,
                descriptor.Name));
 }
 public ResultBuilderDescriptor(
     string name,
     INamedTypeDescriptor resultNamedType,
     IReadOnlyCollection <ValueParserDescriptor> valueParsers)
 {
     _name           = name;
     ResultNamedType = resultNamedType;
     RuntimeType     = new(NamingConventions.CreateResultBuilderName(_name));
     ValueParsers    = valueParsers;
 }
        private void AddUpdateEntityMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            INamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed)
        {
            methodBuilder.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"{TypeNames.EntityId} {_entityId}")
                .SetRighthandSide(
                    MethodCallBuilder
                    .Inline()
                    .SetMethodName(_idSerializer, "Parse")
                    .AddArgument($"{_obj}.Value")));

            methodBuilder.AddCode(
                MethodCallBuilder
                .New()
                .SetMethodName(_entityIds, nameof(List <object> .Add))
                .AddArgument(_entityId));

            methodBuilder.AddEmptyLine();

            if (namedTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                // If the type is an interface
                foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy)
                {
                    methodBuilder
                    .AddEmptyLine()
                    .AddCode(CreateUpdateEntityStatement(concreteType)
                             .AddCode($"return {_entityId};"));
                }

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException));
            }
            else if (namedTypeDescriptor is ObjectTypeDescriptor objectTypeDescriptor)
            {
                BuildTryGetEntityIf(
                    CreateEntityType(
                        objectTypeDescriptor.Name,
                        objectTypeDescriptor.RuntimeType.NamespaceWithoutGlobal))
                .AddCode(CreateEntityConstructorCall(objectTypeDescriptor, false))
                .AddElse(CreateEntityConstructorCall(objectTypeDescriptor, true));

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode($"return {_entityId};");
            }

            AddRequiredDeserializeMethods(namedTypeDescriptor, classBuilder, processed);
        }
Example #10
0
        private static ITypeDescriptor Rewrite(
            IType type,
            INamedTypeDescriptor namedTypeDescriptor)
        {
            switch (type)
            {
            case NonNullType nnt:
                return(new NonNullTypeDescriptor(Rewrite(nnt.InnerType(), namedTypeDescriptor)));

            case ListType lt:
                return(new ListTypeDescriptor(Rewrite(lt.InnerType(), namedTypeDescriptor)));

            case INamedType:
                return(namedTypeDescriptor);

            default:
                throw new InvalidOperationException();
            }
        }
Example #11
0
        private void AddUpdateEntityMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            INamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed)
        {
            methodBuilder.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"{TypeNames.EntityId} {_entityId}")
                .SetRighthandSide(
                    MethodCallBuilder
                    .Inline()
                    .SetMethodName(_extractId)
                    .AddArgument($"{_obj}.{nameof(Nullable<EntityId>.Value)}")));

            methodBuilder.AddCode(
                MethodCallBuilder
                .New()
                .SetMethodName(_entityIds, nameof(List <object> .Add))
                .AddArgument(_entityId));

            methodBuilder.AddEmptyLine();

            if (namedTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                // If the type is an interface
                foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy)
                {
                    IfBuilder ifStatement = IfBuilder
                                            .New()
                                            .SetCondition(
                        MethodCallBuilder
                        .Inline()
                        .SetMethodName(
                            _entityId,
                            nameof(EntityId.Name),
                            nameof(string.Equals))
                        .AddArgument(concreteType.Name.AsStringToken())
                        .AddArgument(TypeNames.OrdinalStringComparison));

                    var entityTypeName = CreateEntityTypeName(concreteType.Name);

                    WriteEntityLoader(
                        ifStatement,
                        entityTypeName);

                    WritePropertyAssignments(
                        ifStatement,
                        concreteType.Properties);

                    ifStatement
                    .AddEmptyLine()
                    .AddCode($"return {_entityId};");

                    methodBuilder
                    .AddEmptyLine()
                    .AddCode(ifStatement);
                }

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException));
            }
            else if (namedTypeDescriptor is ComplexTypeDescriptor complexTypeDescriptor)
            {
                WriteEntityLoader(methodBuilder, CreateEntityTypeName(namedTypeDescriptor.Name));
                WritePropertyAssignments(methodBuilder, complexTypeDescriptor.Properties);

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode($"return {_entityId};");
            }

            AddRequiredDeserializeMethods(namedTypeDescriptor, classBuilder, processed);
        }
Example #12
0
        private void AddUpdateEntityMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            INamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed)
        {
            var entityIdVarName = "entityId";

            methodBuilder.AddCode(
                AssignmentBuilder.New()
                .SetLefthandSide(
                    CodeBlockBuilder.New()
                    .AddCode(TypeNames.EntityId)
                    .AddCode($" {entityIdVarName}"))
                .SetRighthandSide($"{_extractIdFieldName}({_objParamName}.Value)"));

            methodBuilder.AddCode($"{_entityIdsParam}.Add({entityIdVarName});");
            methodBuilder.AddEmptyLine();

            var entityVarName = "entity";

            if (namedTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                // If the type is an interface
                foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy)
                {
                    methodBuilder.AddEmptyLine();
                    var ifStatement = IfBuilder.New()
                                      .SetCondition(
                        $"entityId.Name.Equals(\"{concreteType.Name}\", " +
                        $"{TypeNames.OrdinalStringComparison})");

                    var entityTypeName = CreateEntityTypeName(concreteType.Name);

                    WriteEntityLoader(
                        ifStatement,
                        entityTypeName,
                        entityVarName,
                        entityIdVarName);

                    WritePropertyAssignments(
                        ifStatement,
                        concreteType.Properties,
                        entityVarName);

                    ifStatement.AddEmptyLine();
                    ifStatement.AddCode($"return {entityIdVarName};");
                    methodBuilder.AddCode(ifStatement);
                }

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode($"throw new {TypeNames.NotSupportedException}();");
            }
            else if (namedTypeDescriptor is ComplexTypeDescriptor complexTypeDescriptor)
            {
                WriteEntityLoader(
                    methodBuilder,
                    CreateEntityTypeName(namedTypeDescriptor.Name),
                    entityVarName,
                    entityIdVarName);

                WritePropertyAssignments(
                    methodBuilder,
                    complexTypeDescriptor.Properties,
                    entityVarName);

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode($"return {entityIdVarName};");
            }

            AddRequiredDeserializeMethods(
                namedTypeDescriptor,
                classBuilder,
                processed);
        }
Example #13
0
        private ICode GenerateInternalMethodBody(DependencyInjectionDescriptor descriptor)
        {
            bool hasSubscriptions =
                descriptor.Operations.OfType <SubscriptionOperationDescriptor>().Any();
            bool hasQueries =
                descriptor.Operations.OfType <QueryOperationDescriptor>().Any();
            bool hasMutations =
                descriptor.Operations.OfType <MutationOperationDescriptor>().Any();

            var body = CodeBlockBuilder
                       .New()
                       .AddCode(_staticCode);

            if (hasSubscriptions)
            {
                body.AddCode(RegisterWebSocketConnection(descriptor.Name));
            }

            if (hasQueries || hasMutations)
            {
                body.AddCode(RegisterHttpConnection(descriptor.Name));
            }

            body.AddEmptyLine();

            foreach (var typeDescriptor in descriptor.TypeDescriptors
                     .OfType <INamedTypeDescriptor>())
            {
                if (typeDescriptor.Kind == TypeKind.EntityType && !typeDescriptor.IsInterface())
                {
                    INamedTypeDescriptor namedTypeDescriptor =
                        (INamedTypeDescriptor)typeDescriptor.NamedType();
                    NameString className = namedTypeDescriptor.ExtractMapperName();

                    var interfaceName =
                        TypeNames.IEntityMapper.WithGeneric(
                            namedTypeDescriptor.ExtractTypeName(),
                            typeDescriptor.RuntimeType.Name);

                    body.AddMethodCall()
                    .SetMethodName(TypeNames.AddSingleton)
                    .AddGeneric(interfaceName)
                    .AddGeneric(className)
                    .AddArgument(_services);
                }
            }

            body.AddEmptyLine();

            foreach (var enumType in descriptor.EnumTypeDescriptor)
            {
                body.AddMethodCall()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(TypeNames.ISerializer)
                .AddGeneric(CreateEnumParserName(enumType.Name))
                .AddArgument(_services);
            }

            foreach (var serializer in _serializers)
            {
                body.AddMethodCall()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(TypeNames.ISerializer)
                .AddGeneric(serializer)
                .AddArgument(_services);
            }

            RuntimeTypeInfo stringTypeInfo = TypeInfos.From(TypeNames.String);

            foreach (var scalar in descriptor.TypeDescriptors.OfType <ScalarTypeDescriptor>())
            {
                if (scalar.RuntimeType.Equals(stringTypeInfo) &&
                    scalar.SerializationType.Equals(stringTypeInfo) &&
                    !BuiltInScalarNames.IsBuiltInScalar(scalar.Name))
                {
                    body.AddMethodCall()
                    .SetMethodName(TypeNames.AddSingleton)
                    .AddGeneric(TypeNames.ISerializer)
                    .AddArgument(_services)
                    .AddArgument(MethodCallBuilder
                                 .Inline()
                                 .SetNew()
                                 .SetMethodName(TypeNames.StringSerializer)
                                 .AddArgument(scalar.Name.AsStringToken()));
                }
            }

            foreach (var inputTypeDescriptor in descriptor.TypeDescriptors
                     .Where(x => x.Kind is TypeKind.InputType))
            {
                body.AddMethodCall()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(TypeNames.ISerializer)
                .AddGeneric(CreateInputValueFormatter(
                                (InputObjectTypeDescriptor)inputTypeDescriptor.NamedType()))
                .AddArgument(_services);
            }

            body.AddCode(RegisterSerializerResolver());

            body.AddEmptyLine();

            foreach (var operation in descriptor.Operations)
            {
                if (!(operation.ResultTypeReference is InterfaceTypeDescriptor typeDescriptor))
                {
                    continue;
                }

                string connectionKind = operation is SubscriptionOperationDescriptor
                    ? TypeNames.WebSocketConnection
                    : TypeNames.HttpConnection;
                NameString operationName      = operation.OperationName;
                NameString fullName           = operation.Name;
                NameString operationInterface = typeDescriptor.RuntimeType.Name;

                // The factories are generated based on the concrete result type, which is the
                // only implementee of the result type interface.

                var factoryName =
                    CreateResultFactoryName(
                        typeDescriptor.ImplementedBy.First().RuntimeType.Name);

                var builderName = CreateResultBuilderName(operationName);
                body.AddCode(
                    RegisterOperation(
                        connectionKind,
                        fullName,
                        operationInterface,
                        factoryName,
                        builderName));
            }

            body.AddCode(
                MethodCallBuilder
                .New()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(descriptor.RuntimeType.Name)
                .AddArgument(_services));

            body.AddLine($"return {_services};");

            return(body);
        }
Example #14
0
 public static NameString ExtractTypeName(this INamedTypeDescriptor descriptor)
 {
     return(descriptor.IsEntityType()
         ? CreateEntityTypeName(descriptor.Name)
         : descriptor.Name);
 }
Example #15
0
        public static void Map(ClientModel model, IMapperContext context)
        {
            foreach (OperationModel modelOperation in model.Operations)
            {
                var arguments = modelOperation.Arguments.Select(
                    arg =>
                {
                    NameString typeName = arg.Type.TypeName();

                    INamedTypeDescriptor namedTypeDescriptor =
                        context.Types.Single(type => type.Name.Equals(typeName));

                    return(new PropertyDescriptor(
                               arg.Name,
                               arg.Variable.Variable.Name.Value,
                               Rewrite(arg.Type, namedTypeDescriptor),
                               null));
                })
                                .ToList();

                RuntimeTypeInfo resultType = context.GetRuntimeType(
                    modelOperation.ResultType.Name,
                    Descriptors.TypeDescriptors.TypeKind.ResultType);

                string bodyString = modelOperation.Document.ToString();
                byte[] body       = Encoding.UTF8.GetBytes(modelOperation.Document.ToString(false));
                string hash       = context.HashProvider.ComputeHash(body);

                switch (modelOperation.OperationType)
                {
                case OperationType.Query:
                    context.Register(
                        modelOperation.Name,
                        new QueryOperationDescriptor(
                            modelOperation.Name,
                            context.Namespace,
                            context.Types.Single(t => t.RuntimeType.Equals(resultType)),
                            arguments,
                            body,
                            bodyString,
                            context.HashProvider.Name,
                            hash,
                            context.RequestStrategy));
                    break;

                case OperationType.Mutation:
                    context.Register(
                        modelOperation.Name,
                        new MutationOperationDescriptor(
                            modelOperation.Name,
                            context.Namespace,
                            context.Types.Single(t => t.RuntimeType.Equals(resultType)),
                            arguments,
                            body,
                            bodyString,
                            context.HashProvider.Name,
                            hash,
                            context.RequestStrategy));
                    break;

                case OperationType.Subscription:
                    context.Register(
                        modelOperation.Name,
                        new SubscriptionOperationDescriptor(
                            modelOperation.Name,
                            context.Namespace,
                            context.Types.Single(t => t.RuntimeType.Equals(resultType)),
                            arguments,
                            body,
                            bodyString,
                            context.HashProvider.Name,
                            hash,
                            context.RequestStrategy));
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
        }
Example #16
0
        private static ICode GenerateInternalMethodBody(
            CSharpSyntaxGeneratorSettings settings,
            DependencyInjectionDescriptor descriptor,
            TransportProfile profile)
        {
            var rootNamespace = descriptor.ClientDescriptor.RuntimeType.Namespace;

            var hasSubscriptions =
                descriptor.Operations.OfType <SubscriptionOperationDescriptor>().Any();
            var hasQueries =
                descriptor.Operations.OfType <QueryOperationDescriptor>().Any();
            var hasMutations =
                descriptor.Operations.OfType <MutationOperationDescriptor>().Any();

            CodeBlockBuilder body = CodeBlockBuilder
                                    .New()
                                    .AddCode(CreateBaseCode(settings));

            var generatedConnections = new HashSet <TransportType>();

            if (hasSubscriptions)
            {
                generatedConnections.Add(profile.Subscription);
                body.AddCode(
                    RegisterConnection(profile.Subscription, descriptor.Name));
            }

            if (hasQueries && !generatedConnections.Contains(profile.Query))
            {
                generatedConnections.Add(profile.Query);
                body.AddCode(RegisterConnection(profile.Query, descriptor.Name));
            }

            if (hasMutations && !generatedConnections.Contains(profile.Mutation))
            {
                generatedConnections.Add(profile.Mutation);
                body.AddCode(RegisterConnection(profile.Mutation, descriptor.Name));
            }

            body.AddEmptyLine();

            foreach (var typeDescriptor in descriptor.TypeDescriptors
                     .OfType <INamedTypeDescriptor>())
            {
                if (typeDescriptor.Kind == TypeKind.Entity && !typeDescriptor.IsInterface())
                {
                    INamedTypeDescriptor namedTypeDescriptor =
                        (INamedTypeDescriptor)typeDescriptor.NamedType();
                    NameString className = namedTypeDescriptor.ExtractMapperName();

                    var interfaceName =
                        TypeNames.IEntityMapper.WithGeneric(
                            namedTypeDescriptor.ExtractType().ToString(),
                            $"{rootNamespace}.{typeDescriptor.RuntimeType.Name}");

                    body.AddMethodCall()
                    .SetMethodName(TypeNames.AddSingleton)
                    .AddGeneric(interfaceName)
                    .AddGeneric($"{CreateStateNamespace(rootNamespace)}.{className}")
                    .AddArgument(_services);
                }
            }

            body.AddEmptyLine();

            foreach (var enumType in descriptor.EnumTypeDescriptor)
            {
                body.AddMethodCall()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(TypeNames.ISerializer)
                .AddGeneric(CreateEnumParserName($"{rootNamespace}.{enumType.Name}"))
                .AddArgument(_services);
            }

            foreach (var serializer in _serializers)
            {
                body.AddMethodCall()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(TypeNames.ISerializer)
                .AddGeneric(serializer)
                .AddArgument(_services);
            }

            RuntimeTypeInfo stringTypeInfo = new RuntimeTypeInfo(TypeNames.String);

            foreach (var scalar in descriptor.TypeDescriptors.OfType <ScalarTypeDescriptor>())
            {
                if (scalar.RuntimeType.Equals(stringTypeInfo) &&
                    scalar.SerializationType.Equals(stringTypeInfo) &&
                    !BuiltInScalarNames.IsBuiltInScalar(scalar.Name))
                {
                    body.AddMethodCall()
                    .SetMethodName(TypeNames.AddSingleton)
                    .AddGeneric(TypeNames.ISerializer)
                    .AddArgument(_services)
                    .AddArgument(MethodCallBuilder
                                 .Inline()
                                 .SetNew()
                                 .SetMethodName(TypeNames.StringSerializer)
                                 .AddArgument(scalar.Name.AsStringToken()));
                }
            }

            foreach (var inputTypeDescriptor in descriptor.TypeDescriptors
                     .Where(x => x.Kind is TypeKind.Input))
            {
                var formatter =
                    CreateInputValueFormatter(
                        (InputObjectTypeDescriptor)inputTypeDescriptor.NamedType());

                body.AddMethodCall()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(TypeNames.ISerializer)
                .AddGeneric($"{rootNamespace}.{formatter}")
                .AddArgument(_services);
            }

            body.AddCode(RegisterSerializerResolver());

            body.AddEmptyLine();

            foreach (var operation in descriptor.Operations)
            {
                if (!(operation.ResultTypeReference is InterfaceTypeDescriptor typeDescriptor))
                {
                    continue;
                }

                TransportType operationKind = operation switch
                {
                    SubscriptionOperationDescriptor => profile.Subscription,
                    QueryOperationDescriptor => profile.Query,
                    MutationOperationDescriptor => profile.Mutation,
                    _ => throw ThrowHelper.DependencyInjection_InvalidOperationKind(operation)
                };

                string connectionKind = operationKind switch
                {
                    TransportType.Http => TypeNames.IHttpConnection,
                    TransportType.WebSocket => TypeNames.IWebSocketConnection,
                    TransportType.InMemory => TypeNames.IInMemoryConnection,
                    { } v => throw ThrowHelper.DependencyInjection_InvalidTransportType(v)
                };

                string operationName          = operation.Name;
                string fullName               = operation.RuntimeType.ToString();
                string operationInterfaceName = operation.InterfaceType.ToString();
                string resultInterface        = typeDescriptor.RuntimeType.ToString();

                // The factories are generated based on the concrete result type, which is the
                // only implementee of the result type interface.

                var factoryName =
                    CreateResultFactoryName(
                        typeDescriptor.ImplementedBy.First().RuntimeType.Name);

                var builderName = CreateResultBuilderName(operationName);
                body.AddCode(
                    RegisterOperation(
                        settings,
                        connectionKind,
                        fullName,
                        operationInterfaceName,
                        resultInterface,
                        $"{CreateStateNamespace(operation.RuntimeType.Namespace)}.{factoryName}",
                        $"{CreateStateNamespace(operation.RuntimeType.Namespace)}.{builderName}"));
            }

            if (settings.IsStoreEnabled())
            {
                body.AddCode(
                    MethodCallBuilder
                    .New()
                    .SetMethodName(TypeNames.AddSingleton)
                    .AddGeneric(TypeNames.IEntityIdSerializer)
                    .AddGeneric(descriptor.EntityIdFactoryDescriptor.Type.ToString())
                    .AddArgument(_services));
            }

            body.AddCode(
                MethodCallBuilder
                .New()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(descriptor.ClientDescriptor.RuntimeType.ToString())
                .AddArgument(_services));

            body.AddCode(
                MethodCallBuilder
                .New()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(descriptor.ClientDescriptor.InterfaceType.ToString())
                .AddArgument(_services)
                .AddArgument(LambdaBuilder
                             .New()
                             .AddArgument(_sp)
                             .SetCode(MethodCallBuilder
                                      .Inline()
                                      .SetMethodName(TypeNames.GetRequiredService)
                                      .AddGeneric(descriptor.ClientDescriptor.RuntimeType.ToString())
                                      .AddArgument(_sp))));

            body.AddLine($"return {_services};");

            return(body);
        }
Example #17
0
        private ICode GenerateInternalMethodBody(DependencyInjectionDescriptor descriptor)
        {
            bool hasSubscriptions =
                descriptor.Operations.OfType <SubscriptionOperationDescriptor>().Any();
            bool hasQueries =
                descriptor.Operations.OfType <QueryOperationDescriptor>().Any();
            bool hasMutations =
                descriptor.Operations.OfType <MutationOperationDescriptor>().Any();

            var stringBuilder = new StringBuilder();
            var codeWriter    = new CodeWriter(stringBuilder);

            stringBuilder.AppendLine(_staticCode);

            codeWriter.WriteComment("register connections");

            if (hasSubscriptions)
            {
                stringBuilder.AppendLine(RegisterWebSocketConnection(descriptor.Name));
            }

            if (hasQueries || hasMutations)
            {
                stringBuilder.AppendLine(RegisterHttpConnection(descriptor.Name));
            }

            codeWriter.WriteComment("register mappers");
            codeWriter.WriteLine();

            foreach (var typeDescriptor in descriptor.TypeDescriptors
                     .OfType <INamedTypeDescriptor>())
            {
                if (typeDescriptor.Kind == TypeKind.EntityType && !typeDescriptor.IsInterface())
                {
                    INamedTypeDescriptor namedTypeDescriptor =
                        (INamedTypeDescriptor)typeDescriptor.NamedType();
                    NameString className = namedTypeDescriptor.ExtractMapperName();

                    var interfaceName =
                        TypeNames.IEntityMapper.WithGeneric(
                            namedTypeDescriptor.ExtractTypeName(),
                            typeDescriptor.RuntimeType.Name);

                    AddSingleton(codeWriter, interfaceName, className);
                }
            }

            codeWriter.WriteLine();
            codeWriter.WriteComment("register serializers");
            codeWriter.WriteLine();

            foreach (var enumType in descriptor.EnumTypeDescriptor)
            {
                AddSingleton(
                    codeWriter,
                    TypeNames.ISerializer,
                    CreateEnumParserName(enumType.Name));
            }

            foreach (var serializer in _serializers)
            {
                AddSingleton(
                    codeWriter,
                    TypeNames.ISerializer,
                    serializer);
            }

            foreach (var inputTypeDescriptor in descriptor.TypeDescriptors
                     .Where(x => x.Kind is TypeKind.InputType))
            {
                AddSingleton(
                    codeWriter,
                    TypeNames.ISerializer,
                    CreateInputValueFormatter(
                        (InputObjectTypeDescriptor)inputTypeDescriptor.NamedType()));
            }

            RegisterSerializerResolver().Build(codeWriter);

            codeWriter.WriteLine();
            codeWriter.WriteComment("register operations");
            foreach (var operation in descriptor.Operations)
            {
                if (!(operation.ResultTypeReference is InterfaceTypeDescriptor typeDescriptor))
                {
                    continue;
                }

                string connectionKind = operation is SubscriptionOperationDescriptor
                    ? TypeNames.WebSocketConnection
                    : TypeNames.HttpConnection;
                NameString operationName      = operation.OperationName;
                NameString fullName           = operation.Name;
                NameString operationInterface = typeDescriptor.RuntimeType.Name;

                // The factories are generated based on the concrete result type, which is the
                // only implementee of the result type interface.

                var factoryName =
                    CreateResultFactoryName(
                        typeDescriptor.ImplementedBy.First().RuntimeType.Name);

                var builderName = CreateResultBuilderName(operationName);
                stringBuilder.AppendLine(
                    RegisterOperation(
                        connectionKind,
                        descriptor.RuntimeType.Name,
                        fullName,
                        operationInterface,
                        factoryName,
                        builderName));
            }

            stringBuilder.AppendLine(
                $"{TypeNames.AddSingleton.WithGeneric(descriptor.RuntimeType.Name)}(services);");

            stringBuilder.AppendLine();
            stringBuilder.AppendLine("return services;");

            return(CodeBlockBuilder.From(stringBuilder));
        }