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)
            {
                if (typeDescriptor.Kind == TypeKind.EntityType && !typeDescriptor.IsInterface())
                {
                    NamedTypeDescriptor namedTypeDescriptor =
                        (NamedTypeDescriptor)typeDescriptor.NamedType();
                    NameString className = namedTypeDescriptor.ExtractMapperName();

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

                    AddSingleton(codeWriter, interfaceName, className);
                }
            }

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

            foreach (var enumType in descriptor.EnumTypeDescriptor)
            {
                AddSingleton(
                    codeWriter,
                    TypeNames.ISerializer,
                    EnumParserNameFromEnumName(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,
                    InputValueFormatterFromType(
                        (NamedTypeDescriptor)inputTypeDescriptor.NamedType()));
            }

            RegisterSerializerResolver().Build(codeWriter);

            codeWriter.WriteLine();
            codeWriter.WriteComment("register operations");
            foreach (var operation in descriptor.Operations)
            {
                string connectionKind = operation is SubscriptionOperationDescriptor
                    ? TypeNames.WebSocketConnection
                    : TypeNames.HttpConnection;
                NameString operationName      = operation.OperationName;
                NameString fullName           = operation.Name;
                NameString operationInterface = operation.ResultTypeReference.Name;

                // The resulttype of the operation is a NamedTypeDescriptor, that is an Interface
                var resultType = operation.ResultTypeReference as NamedTypeDescriptor
                                 ?? throw new ArgumentException("ResultTypeReference");
                // The factories are generated based on the concrete result type, which is the
                // only implementee of the result type interface.
                var factoryName = ResultFactoryNameFromTypeName(resultType.ImplementedBy[0].Name);

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

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

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

            return(CodeBlockBuilder.From(stringBuilder));
        }
        protected override void Generate(
            CodeWriter writer,
            ITypeDescriptor typeDescriptor,
            out string fileName)
        {
            var(classBuilder, constructorBuilder) = CreateClassBuilder(false);

            NamedTypeDescriptor descriptor = (NamedTypeDescriptor)typeDescriptor.NamedType();

            // Setup class
            fileName = descriptor.ExtractMapperName();

            classBuilder
            .AddImplements(
                TypeNames.IEntityMapper
                .WithGeneric(descriptor.ExtractTypeName(), descriptor.Name))
            .SetName(fileName);

            constructorBuilder.SetTypeName(descriptor.Name);

            if (descriptor.ContainsEntity())
            {
                AddConstructorAssignedField(
                    TypeNames.IEntityStore,
                    StoreFieldName,
                    classBuilder,
                    constructorBuilder);
            }

            // Define map method
            MethodBuilder mapMethod = MethodBuilder.New()
                                      .SetName(_mapMethodName)
                                      .SetAccessModifier(AccessModifier.Public)
                                      .SetReturnType(descriptor.Name)
                                      .AddParameter(
                ParameterBuilder.New()
                .SetType(
                    descriptor.Kind == TypeKind.EntityType
                                ? EntityTypeNameFromGraphQLTypeName(descriptor.GraphQLTypeName)
                                : descriptor.Name)
                .SetName(_entityParamName));

            var constructorCall =
                MethodCallBuilder
                .New()
                .SetMethodName($"return new {descriptor.Name}");

            if (typeDescriptor is NamedTypeDescriptor namedTypeDescriptor)
            {
                foreach (PropertyDescriptor property in namedTypeDescriptor.Properties)
                {
                    constructorCall.AddArgument(BuildMapMethodCall(_entityParamName, property));
                }
            }

            mapMethod.AddCode(constructorCall);

            if (constructorBuilder.HasParameters())
            {
                classBuilder.AddConstructor(constructorBuilder);
            }

            classBuilder.AddMethod(mapMethod);

            var processed = new HashSet <string>();

            AddRequiredMapMethods(
                _entityParamName,
                descriptor,
                classBuilder,
                constructorBuilder,
                processed);

            CodeFileBuilder
            .New()
            .SetNamespace(descriptor.Namespace)
            .AddType(classBuilder)
            .Build(writer);
        }