in packages/jsii-pacmak/lib/targets/dotnet/dotnetgenerator.ts [325:451]
protected onBeginClass(cls: spec.ClassType, abstract: boolean) {
let baseTypeNames: string[] = [];
const namespace = this.namespaceFor(this.assembly, cls);
// A class can derive from only one base class
// But can implement multiple interfaces
if (!cls.base) {
baseTypeNames.push('DeputyBase');
} else {
const classBase = this.typeresolver.toDotNetType({ fqn: cls.base });
baseTypeNames.push(classBase);
}
if (cls.interfaces && cls.interfaces.length > 0) {
const implementations =
this.typeresolver.resolveImplementedInterfaces(cls);
baseTypeNames = baseTypeNames.concat(implementations);
}
const className = this.nameutils.convertClassName(cls);
// Nested classes will be dealt with during calc code generation
const nested = this.isNested(cls);
const absPrefix = abstract ? ' abstract' : '';
this.openFileIfNeeded(className, namespace, nested);
const implementsExpr = ` : ${baseTypeNames.join(', ')}`;
this.dotnetDocGenerator.emitDocs(cls, {
api: 'type',
fqn: cls.fqn,
});
this.dotnetRuntimeGenerator.emitAttributesForClass(cls);
this.code.openBlock(
`public${absPrefix} class ${className}${implementsExpr}`,
);
// Compute the class parameters
let parametersDefinition = '';
let parametersBase = '';
const initializer = cls.initializer;
if (initializer) {
this.dotnetDocGenerator.emitDocs(initializer, {
api: 'initializer',
fqn: cls.fqn,
});
this.dotnetRuntimeGenerator.emitDeprecatedAttributeIfNecessary(
initializer,
);
if (initializer.parameters) {
parametersDefinition = this.renderParametersString(
initializer.parameters,
);
for (const p of initializer.parameters) {
parametersBase += `${this.nameutils.convertParameterName(p.name)}`;
// If this is not the last parameter, append ,
if (
initializer.parameters.indexOf(p) !==
initializer.parameters.length - 1
) {
parametersBase += ', ';
}
}
}
// Create the constructors:
// Abstract classes have protected constructors.
const visibility = cls.abstract ? 'protected' : 'public';
this.code.openBlock(
`${visibility} ${className}(${parametersDefinition}): base(_MakeDeputyProps(${parametersBase}))`,
);
this.code.closeBlock();
this.code.line();
// This private method is injected so we can validate arguments before deferring to the base constructor, where
// the instance will be created in the kernel (where it'd fail on a sub-optimal error instead)...
this.code.line(
'[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]',
);
this.code.openBlock(
`private static DeputyProps _MakeDeputyProps(${parametersDefinition})`,
);
this.emitUnionParameterValdation(
(this.reflectAssembly.findType(cls.fqn) as reflect.ClassType)
.initializer?.parameters,
);
const args =
parametersBase.length > 0
? `new object?[]{${parametersBase}}`
: `System.Array.Empty<object?>()`;
this.code.line(`return new DeputyProps(${args});`);
this.code.closeBlock();
this.code.line();
}
this.code.line(
'/// <summary>Used by jsii to construct an instance of this class from a Javascript-owned object reference</summary>',
);
this.code.line(
'/// <param name="reference">The Javascript-owned object reference</param>',
);
this.dotnetRuntimeGenerator.emitDeprecatedAttributeIfNecessary(initializer);
this.emitHideAttribute();
this.code.openBlock(
`protected ${className}(ByRefValue reference): base(reference)`,
);
this.code.closeBlock();
this.code.line();
this.code.line(
'/// <summary>Used by jsii to construct an instance of this class from DeputyProps</summary>',
);
this.code.line('/// <param name="props">The deputy props</param>');
this.dotnetRuntimeGenerator.emitDeprecatedAttributeIfNecessary(initializer);
this.emitHideAttribute();
this.code.openBlock(
`protected ${className}(DeputyProps props): base(props)`,
);
this.code.closeBlock();
// We have already outputted members (constructors), setting the flag to true
this.flagFirstMemberWritten(true);
}