private Method CreateMethod()

in src/AutoRest.CSharp/Common/Output/Models/Types/ModelFactoryTypeProvider.cs [208:307]


        private Method CreateMethod(SerializableObjectType model)
        {
            var ctor = model.SerializationConstructor;
            var ctorToCall = ctor;
            var discriminator = model.Discriminator;
            if (model.Declaration.IsAbstract && discriminator != null)
            {
                // the model factory entry method `RequiresModelFactory` makes sure this: if this model is abstract, the discriminator must not be null
                ctorToCall = discriminator.DefaultObjectType.SerializationConstructor;
            }
            var methodParameters = new List<Parameter>(ctor.Signature.Parameters.Count);
            var methodArguments = new List<ValueExpression>(ctor.Signature.Parameters.Count);

            foreach (var ctorParameter in ctorToCall.Signature.Parameters)
            {
                var property = ctorToCall.FindPropertyInitializedByParameter(ctorParameter);
                if (property == null)
                {
                    // if the property is not found, in order not to introduce compilation errors, we need to add a `default` into the argument list
                    methodArguments.Add(new PositionalParameterReference(ctorParameter.Name, Default));
                    continue;
                }

                if (ctorParameter.IsRawData)
                {
                    // we do not want to include the raw data as a parameter of the model factory entry method, therefore here we skip the parameter, and use empty dictionary as argument
                    methodArguments.Add(new PositionalParameterReference(ctorParameter.Name, Null));
                    continue;
                }

                if (property.FlattenedProperty != null)
                    property = property.FlattenedProperty;

                var parameterName = property.Declaration.Name.ToVariableName();
                var inputType = property.Declaration.Type;
                // check if the property is the discriminator, but skip the check if the configuration is on for HLC only
                if (discriminator != null && discriminator.Property == property && !Configuration.ModelFactoryForHlc.Contains(model.Declaration.Name))
                {
                    if (discriminator.Value is { } value)
                    {
                        // this is a derived class, we do not add this parameter to the method, but we need an argument for the invocation
                        methodArguments.Add(new ConstantExpression(value));
                        continue;
                    }
                    // this class is the base in a discriminated set
                    switch (inputType)
                    {
                        case { IsFrameworkType: false, Implementation: EnumType { IsExtensible: true } extensibleEnum }:
                            inputType = extensibleEnum.ValueType;
                            break;
                        case { IsFrameworkType: false, Implementation: EnumType { IsExtensible: false } }:
                            // we skip the parameter if the discriminator is a sealed choice because we can never pass in a "Unknown" value.
                            // but we still need to add it to the method argument list as a `default`
                            methodArguments.Add(Default);
                            continue;
                        default:
                            break;
                    }
                }

                inputType = inputType.InputType;
                if (!inputType.IsValueType)
                {
                    inputType = inputType.WithNullable(true);
                }

                var parameter = ctorParameter with
                {
                    Name = parameterName,
                    Type = inputType,
                    DefaultValue = Constant.Default(inputType),
                    Initializer = inputType.GetParameterInitializer(ctorParameter.DefaultValue)
                };

                methodParameters.Add(parameter);

                var expression = BuildPropertyAssignmentExpression(parameter, property).GetConversion(parameter.Type, ctorParameter.Type);
                methodArguments.Add(expression);
            }

            FormattableString returnDescription = $"A new {model.Type:C} instance for mocking.";

            var signature = new MethodSignature(
                ctor.Signature.Name,
                ctor.Signature.Summary,
                ctor.Signature.Description,
                MethodSignatureModifiers.Public | MethodSignatureModifiers.Static,
                model.Type,
                returnDescription,
                methodParameters);

            var methodBody = new MethodBodyStatement[]
            {
                // write the initializers and validations
                new ParameterValidationBlock(methodParameters, true),
                Return(New.Instance(ctorToCall.Signature, methodArguments))
            };

            return new(signature, methodBody);
        }