示例#1
0
        private IEnumerable <MemberDeclarationSyntax> GenerateUploadMembers(SourceFileContext ctx)
        {
            var uploadTyp = Typ.Nested(ctx.CurrentTyp, PascalCasedName + "MediaUpload");

            var baseTypArgument1 = BodyTyp ?? Typ.Of <string>();
            var baseTyp          = _restMethod.Response is object
                                   ?Typ.Generic(Typ.Of(typeof(ResumableUpload <,>)), baseTypArgument1, ResponseTyp)
                                       : Typ.Generic(Typ.Of(typeof(ResumableUpload <>)), baseTypArgument1);

            var uploadCls = Class(Modifier.Public, uploadTyp, ctx.Type(baseTyp))
                            .WithXmlDoc(XmlDoc.Summary($"{PascalCasedName} media upload which supports resumable upload."));

            var parameters         = CreateParameterList(uploadTyp);
            var requiredParameters = parameters
                                     .TakeWhile(p => p.IsRequired)
                                     .Select(p => (param: p, decl: Parameter(ctx.Type(p.Typ), p.CodeParameterName)))
                                     .ToList();

            var insertMethodParameters = new List <ParameterSyntax>();

            if (BodyTyp is object)
            {
                insertMethodParameters.Add(Parameter(ctx.Type(BodyTyp), "body"));
            }
            insertMethodParameters.AddRange(requiredParameters.Select(pair => pair.decl));
            var streamParam = Parameter(ctx.Type <Stream>(), "stream");

            var contentTypeParam = Parameter(ctx.Type <string>(), "contentType");

            insertMethodParameters.Add(streamParam);
            insertMethodParameters.Add(contentTypeParam);

            // This doc comment is common between the method and the constructor.
            var remarks = XmlDoc.Remarks("Considerations regarding ", streamParam, ":",
                                         XmlDoc.BulletListOfItemNodes(
                                             XmlDoc.Item("If ", streamParam, " is seekable, then the stream position will be reset to ", 0, " before reading commences. If ", streamParam, " is not seekable, then it will be read from its current position"),
                                             XmlDoc.Item("Caller is responsible for maintaining the ", streamParam, " open until the upload is completed"),
                                             XmlDoc.Item("Caller is responsible for closing the ", streamParam)));

            var methodDocComments = new List <DocumentationCommentTriviaSyntax>
            {
                XmlDoc.Summary(_restMethod.Description),
                remarks
            };

            if (BodyTyp is object)
            {
                methodDocComments.Add(XmlDoc.Param(Parameter(ctx.Type(BodyTyp), "body"), "The body of the request."));
            }

            methodDocComments.AddRange(requiredParameters.Select(pair => XmlDoc.Param(pair.decl, pair.param.Description)));
            methodDocComments.Add(XmlDoc.Param(streamParam, "The stream to upload. See remarks for further information."));
            methodDocComments.Add(XmlDoc.Param(contentTypeParam, "The content type of the stream to upload."));

            // We're taking it from the field in the parent type, but it becomes a parameter for the constructor...
            // So long as it appears as "service" we don't really mind.
            var serviceParam   = Parameter(ctx.Type <IClientService>(), "service");
            var ctorParameters = new List <ParameterSyntax> {
                serviceParam
            };

            ctorParameters.AddRange(insertMethodParameters);

            var insertMethod = Method(Modifier.Public | Modifier.Virtual, ctx.Type(uploadTyp), PascalCasedName)(insertMethodParameters.ToArray())
                               .WithBlockBody(Return(New(ctx.Type(uploadTyp))(ctorParameters)))
                               .WithXmlDoc(methodDocComments.ToArray());

            using (ctx.InClass(uploadTyp))
            {
                var baseInitializerArgs = new List <object>
                {
                    serviceParam,
                    ctx.Type <string>().Call(nameof(string.Format))("/{0}/{1}{2}", "upload", serviceParam.Access("BasePath"), _restMethod.Path),
                    _restMethod.HttpMethod,
                    streamParam,
                    contentTypeParam
                };
                var baseInitializer = BaseInitializer(baseInitializerArgs).WithAdditionalAnnotations(Annotations.LineBreakAnnotation);
                var assignments     = requiredParameters.Select(p => Field(0, ctx.Type(p.param.Typ), p.param.PropertyName).Assign(p.decl)).ToList();

                if (BodyTyp is object)
                {
                    // The Body property is in the base class.
                    var bodyProperty = Property(Modifier.Public, ctx.Type(BodyTyp), "Body");
                    assignments.Add(bodyProperty.Assign(Parameter(ctx.Type(BodyTyp), "body")));
                }

                // The parameters to the constructor are the same as for the method.
                var uploadCtor = Ctor(Modifier.Public, uploadCls, baseInitializer)(ctorParameters.ToArray())
                                 .WithBlockBody(assignments)
                                 .WithXmlDoc(XmlDoc.Summary($"Constructs a new {PascalCasedName} media upload instance."), remarks);

                uploadCls = uploadCls.AddMembers(Package.CreateParameterList(uploadTyp).SelectMany(p => p.GenerateDeclarations(ctx)).ToArray());
                uploadCls = uploadCls.AddMembers(parameters.SelectMany(p => p.GenerateDeclarations(ctx)).ToArray());
                uploadCls = uploadCls.AddMembers(uploadCtor);
            }

            yield return(insertMethod);

            yield return(uploadCls);
        }