powershell/llcsharp/model/model-class-dictionary.ts (84 lines of code) (raw):
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Field, System, Property, toExpression, dotnet, Parameter, ParameterModifier, Method, Class, TypeDeclaration, Indexer, Access, Variable, Expression, If, And, ForEach, LocalVariable, ImplicitCastOperator } from '@azure-tools/codegen-csharp';
import { ModelClass } from './model-class';
import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration';
import { ClientRuntime } from '../clientruntime';
import { getAllVirtualProperties } from '@azure-tools/codemodel-v3';
import { DeepPartial } from '@azure-tools/codegen';
import { DictionarySchema, ObjectSchema, SchemaType, Schema } from '@autorest/codemodel';
export class DictionaryImplementation extends Class {
private get state() { return this.modelClass.state; }
private get schema() { return this.modelClass.schema; }
public valueType!: TypeDeclaration | EnhancedTypeDeclaration;
public ownsDictionary = false;
constructor(protected modelClass: ModelClass, objectInitializer?: DeepPartial<DictionaryImplementation>) {
super(modelClass.namespace, modelClass.name);
this.apply(objectInitializer);
}
init(valueType?: TypeDeclaration, accessViaMember?: Expression) {
if (valueType && accessViaMember) {
this.valueType = valueType;
this.implementIDictionary(this, '', System.String, valueType, accessViaMember);
}
else {
const dictSchema = (<Schema>this.schema).type === SchemaType.Dictionary ? this.schema : this.schema.parents?.immediate?.find((s) => s.type === SchemaType.Dictionary);
if (dictSchema) {
this.ownsDictionary = true;
this.valueType = (<DictionarySchema>dictSchema).elementType.type === SchemaType.Any ? System.Object : this.state.project.modelsNamespace.NewResolveTypeDeclaration((<DictionarySchema>dictSchema).elementType, true, this.state);
this.modelClass.modelInterface.interfaces.push(this.implementIDictionary(this, 'additionalProperties', System.String, this.valueType));
}
}
return this;
}
addSerialization() {
if (this.modelClass.jsonSerializer) {
// add serializer methods.
// this.modelClass.jsonSerializer
}
}
implementIDictionary(targetClass: Class, name: string, keyType: TypeDeclaration, valueType: TypeDeclaration, accessViaMember?: Expression) {
const containerInterfaceType = { declaration: `${ClientRuntime}.IAssociativeArray<${valueType.declaration}>`, allProperties: [] };
const dictionaryInterfaceType = System.Collections.Generic.IDictionary(keyType, valueType);
const itemType = System.Collections.Generic.KeyValuePair(keyType, valueType);
// add the interface to the list of interfaces for the class
targetClass.interfaces.push(containerInterfaceType);
// the backing field
const dictionaryType = System.Collections.Generic.Dictionary(keyType, valueType);
accessViaMember = accessViaMember || targetClass.add(new Field(`__${name}`, dictionaryType, { access: Access.Protected, initialValue: dictionaryType.new() }));
const indexer = targetClass.add(new Indexer(keyType, valueType, { get: toExpression(`${accessViaMember}[index]`), set: toExpression(`${accessViaMember}[index] = value`) }));
// the parameters used in methods.
const pKey = new Parameter('key', keyType);
const pValue = new Parameter('value', valueType);
const pOutValue = new Parameter('value', valueType, { modifier: ParameterModifier.Out });
if (this.state.project.exportPropertiesForDict) {
targetClass.add(new Property(`${containerInterfaceType.declaration}.Keys`, System.Collections.Generic.IEnumerable(keyType), { get: toExpression(`${accessViaMember}.Keys`), getAccess: Access.Explicit }));
targetClass.add(new Property(`${containerInterfaceType.declaration}.Values`, System.Collections.Generic.IEnumerable(valueType), { get: toExpression(`${accessViaMember}.Values`), getAccess: Access.Explicit }));
targetClass.add(new Property(`${containerInterfaceType.declaration}.Count`, dotnet.Int, { get: toExpression(`${accessViaMember}.Count`), getAccess: Access.Explicit }));
}
if (name) {
targetClass.add(new ImplicitCastOperator(dictionaryType, targetClass, `source.${accessViaMember}`));
targetClass.add(new Property(`${containerInterfaceType.declaration}.AdditionalProperties`, dictionaryInterfaceType, { get: toExpression(`${accessViaMember}`), getAccess: Access.Explicit }));
} else {
targetClass.add(new Property(`${containerInterfaceType.declaration}.AdditionalProperties`, dictionaryInterfaceType, { get: toExpression(`${accessViaMember}.AdditionalProperties`), getAccess: Access.Explicit }));
}
targetClass.add(new Method('Add', dotnet.Void, { parameters: [pKey, pValue], body: toExpression(`${accessViaMember}.Add( ${pKey}, ${pValue})`), access: Access.Public }));
targetClass.add(new Method('Clear', dotnet.Void, { body: toExpression(`${accessViaMember}.Clear()`), access: Access.Public }));
targetClass.add(new Method('ContainsKey', dotnet.Bool, { parameters: [pKey], body: toExpression(`${accessViaMember}.ContainsKey( ${pKey})`), access: Access.Public }));
targetClass.add(new Method('Remove', dotnet.Bool, { parameters: [pKey], body: toExpression(`${accessViaMember}.Remove( ${pKey})`), access: Access.Public }));
targetClass.add(new Method('TryGetValue', dotnet.Bool, { parameters: [pKey, pOutValue], body: toExpression(`${accessViaMember}.TryGetValue( ${pKey}, out ${pOutValue})`), access: Access.Public }));
const all = getAllVirtualProperties(this.schema.language.csharp?.virtualProperties);
const exclusions = all.map(each => `"${each.name}"`).join(',');
// add a CopyFrom that takes an IDictionary or PSObject and copies the values into this dictionary
for (const pDictType of [System.Collections.IDictionary, { declaration: 'global::System.Management.Automation.PSObject' }]) {
const pDict = new Parameter('source', pDictType);
targetClass.add(new Method('CopyFrom', dotnet.Void, {
parameters: [pDict], body: function* () {
yield If(pDict.IsNotNull, function* () {
yield ForEach('property', ` Microsoft.Rest.ClientRuntime.PowerShell.TypeConverterExtensions.GetFilteredProperties(${pDict.value}, ${System.Collections.Generic.HashSet(System.String).new()} { ${exclusions} } )`, function* () {
yield If(And('null != property.Key', 'null != property.Value'), function* () {
yield `this.${accessViaMember}.Add(property.Key.ToString(), global::System.Management.Automation.LanguagePrimitives.ConvertTo<${valueType.declaration}>( property.Value));`;
});
});
});
}
}));
}
// return dictionaryInterfaceType;
return containerInterfaceType;
}
public get fileName(): string {
return `${super.fileName}.dictionary`;
}
}