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();
}
}
}