private createProperties()

in powershell/llcsharp/model/model-class.ts [191:371]


  private createProperties() {
    // generate a protected backing field for each
    // and then expand the nested properties into this class forwarding to the member.  

    // add properties
    if (this.schema.language.csharp?.virtualProperties) {

      /* Owned Properties */
      for (const virtualProperty of values(<Array<NewVirtualProperty>>(this.schema.language.csharp.virtualProperties.owned))) {
        let isPolymorphic = false;
        if (virtualProperty.private && virtualProperty.property.schema.type === SchemaType.Object && (<ObjectSchema>virtualProperty.property.schema).discriminator) {
          isPolymorphic = true;
        }
        const actualProperty = virtualProperty.property;
        let n = 0;
        const isRequired = !!(virtualProperty.required && virtualProperty.read && virtualProperty.create && virtualProperty.update);
        const decl = this.state.project.modelsNamespace.NewResolveTypeDeclaration(<NewSchema>actualProperty.schema, isRequired, this.state.path('schema'));

        /* public property */
        const myProperty = new ModelProperty(virtualProperty.name, <NewSchema>actualProperty.schema, isRequired, actualProperty.serializedName, actualProperty.language.csharp?.description || '', this.state.path('properties', n++), {
          initializer: actualProperty.language.csharp?.constantValue ? typeof actualProperty.language.csharp.constantValue === 'string' ? new StringExpression(actualProperty.language.csharp.constantValue) : new LiteralExpression(actualProperty.language.csharp.constantValue) : undefined
        });

        if (virtualProperty.readOnly || actualProperty.language.csharp?.readOnly || actualProperty.readOnly) {
          myProperty.set = undefined;
        }
        myProperty.language = virtualProperty.property.language;

        if (actualProperty.language.csharp?.constantValue !== undefined) {
          myProperty.setAccess = Access.Internal;
          myProperty.set = undefined;
        }

        if (virtualProperty.private && !isPolymorphic) {
          // when properties are inlined, the container accessor can be internalized. I think.
          myProperty.setAccess = Access.Internal;
          myProperty.getAccess = Access.Internal;
        }

        if (virtualProperty.private) {
          this.pMap.set(virtualProperty, myProperty);
        }

        this.ownedProperties.push(this.add(myProperty));

        if (myProperty.getAccess !== Access.Public || myProperty.setAccess !== Access.Public || myProperty.set === undefined || isPolymorphic) {
          /* internal interface property */

          this.add(new Property(`${virtualProperty.originalContainingSchema.language.csharp?.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, decl, {
            description: `Internal Acessors for ${virtualProperty.name}`,
            getAccess: Access.Explicit,
            setAccess: Access.Explicit,
            get: myProperty.get,
            set: myProperty.assignPrivate('value')
          }));
        }

        myProperty.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Owned`] }));
        this.addFormatAttributesToProperty(myProperty, virtualProperty);
      }

      /* Inherited properties. */
      for (const virtualProperty of values(<Array<NewVirtualProperty>>(this.schema.language.csharp.virtualProperties.inherited))) {
        let isPolymorphic = false;
        if (virtualProperty.private && virtualProperty.property.schema.type === SchemaType.Object && (<ObjectSchema>virtualProperty.property.schema).discriminator) {
          isPolymorphic = true;
        }
        // so each parent property that is getting exposed
        // has to be accessed via the field in this.backingFields
        const parentField = <BackingField>this.backingFields.find(each => virtualProperty.accessViaSchema ? virtualProperty.accessViaSchema.language.csharp?.interfaceImplementation.fullName === each.typeDeclaration.declaration : false);

        const isRequired = !!(virtualProperty.required && virtualProperty.read && virtualProperty.create && virtualProperty.update);
        const propertyType = this.state.project.modelsNamespace.NewResolveTypeDeclaration(<NewSchema>virtualProperty.property.schema, isRequired, this.state);
        const requiredPropertyType = this.state.project.modelsNamespace.NewResolveTypeDeclaration(<NewSchema>virtualProperty.property.schema, true, this.state);
        const opsType = this.state.project.modelsNamespace.NewResolveTypeDeclaration(<NewSchema>virtualProperty.originalContainingSchema, false, this.state);
        const via = <NewVirtualProperty>virtualProperty.accessViaProperty;
        const parentCast = `(${virtualProperty.originalContainingSchema.language.csharp?.internalInterfaceImplementation.fullName})`;
        let getFunc = toExpression(`(${parentCast}${parentField.field.name}).${this.accessor(virtualProperty)}`);
        let setFunc = (virtualProperty.readOnly || virtualProperty.property.language.csharp?.constantValue) ? undefined : toExpression(`(${parentCast}${parentField.field.name}).${this.accessor(virtualProperty)} = value ${isRequired ? '' : ` ?? ${requiredPropertyType.defaultOfType}`}`);
        let isConstant = false;
        if (virtualProperty.property.isDiscriminator && this.schema.discriminatorValue) {
          for (const parent of values(this.schema.parents?.all)) {
            if ((<ObjectSchema>parent).discriminator?.property === virtualProperty.property) {
              getFunc = toExpression(`"${this.schema.discriminatorValue}"`);
              setFunc = toExpression(`(${parentCast}${parentField.field.name}).${this.accessor(virtualProperty)} = "${this.schema.discriminatorValue}"`);
              isConstant = true;
              if (virtualProperty.property.language.csharp?.constantValue === undefined && !virtualProperty.readOnly) {
                this.constructorMethod?.add(`this.${parentField.field.name}.${this.accessor(virtualProperty)} = "${this.schema.discriminatorValue}";`);
              }
              break;
            }
          }
        }

        const vp = this.add(new Property(virtualProperty.name, propertyType, {
          description: virtualProperty.property.language.csharp?.description,
          get: getFunc,
          set: setFunc
        }));

        if (virtualProperty.property.language.csharp?.constantValue !== undefined) {
          vp.setAccess = Access.Internal;
          vp.set = undefined;
        }

        if (virtualProperty.private && !isPolymorphic) {
          vp.setAccess = Access.Internal;
          vp.getAccess = Access.Internal;
        }

        if (vp.getAccess !== Access.Public || vp.setAccess !== Access.Public || vp.set === undefined || isPolymorphic) {

          this.add(new Property(`${virtualProperty.originalContainingSchema.language.csharp?.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, propertyType, {
            description: `Internal Acessors for ${virtualProperty.name}`,
            getAccess: Access.Explicit,
            setAccess: Access.Explicit,
            get: toExpression(`(${parentCast}${parentField.field.name}).${via.name}`),
            set: toExpression(`(${parentCast}${parentField.field.name}).${via.name} = value`)
          }));
        }
        if (isConstant) {
          vp.add(new Attribute(ConstantAttribute));
        }
        vp.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Inherited`] }));
        this.addFormatAttributesToProperty(vp, virtualProperty);
      }

      /* Inlined properties. */
      for (const virtualProperty of values(<Array<NewVirtualProperty>>this.schema.language.csharp.virtualProperties.inlined)) {
        let isPolymorphic = false;
        if (virtualProperty.private && virtualProperty.property.schema.type === SchemaType.Object && (<ObjectSchema>virtualProperty.property.schema).discriminator) {
          // continue;
          // can't remove it, it has to be either public or internally implemented.
          isPolymorphic = true;
        }
        const isRequired = !!(virtualProperty.required && virtualProperty.read && virtualProperty.create && virtualProperty.update);
        if (virtualProperty.accessViaProperty) {
          const containingProperty = this.pMap.get(virtualProperty.accessViaProperty);
          if (containingProperty) {

            const propertyType = this.state.project.modelsNamespace.NewResolveTypeDeclaration(<NewSchema>virtualProperty.property.schema, isRequired, this.state);
            const requiredPropertyType = this.state.project.modelsNamespace.NewResolveTypeDeclaration(<NewSchema>virtualProperty.property.schema, true, this.state);

            // regular inlined property
            const vp = new Property(virtualProperty.name, propertyType, {
              description: virtualProperty.property.language.csharp?.description,
              get: toExpression(`${this.accessor(virtualProperty)}`),
              set: (virtualProperty.readOnly || virtualProperty.property.language.csharp?.constantValue) ? undefined : toExpression(`${this.accessor(virtualProperty)} = value ${isRequired ? '' : ` ?? ${requiredPropertyType.defaultOfType}`}`)
            });

            if (!virtualProperty.private || isPolymorphic) {
              this.add(vp);
            }

            if (virtualProperty.private || vp.getAccess !== Access.Public || vp.setAccess !== Access.Public || vp.set === undefined || isPolymorphic) {
              this.add(new Property(`${virtualProperty.originalContainingSchema.language.csharp?.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, propertyType, {
                description: `Internal Acessors for ${virtualProperty.name}`,
                getAccess: Access.Explicit,
                setAccess: Access.Explicit,
                get: vp.get,
                set: toExpression(`${this.accessor(virtualProperty)} = value`)
              }));
            }

            if (virtualProperty.property.language.csharp?.constantValue !== undefined) {
              vp.setAccess = Access.Internal;
              vp.set = undefined;
            }

            vp.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Inlined`] }));
            this.addFormatAttributesToProperty(vp, virtualProperty);
          }
        }
      }

      /* Appended properties. */
      if (this.state.project.resourceGroupAppend && this.state.project.azure && this.schema.extensions && this.schema.extensions['is-return-object']) {
        this.appendResourceGroupName();
      }
    }
  }