in packages/jsii-pacmak/lib/targets/dotnet/dotnetgenerator.ts [567:653]
private emitMethod(
cls: spec.ClassType | spec.InterfaceType,
method: spec.Method,
definingType: spec.Type,
emitForProxyOrDatatype = false,
): void {
this.emitNewLineIfNecessary();
const returnType = method.returns
? this.typeresolver.toDotNetType(method.returns.type)
: 'void';
const staticKeyWord = method.static ? 'static ' : '';
let overrideKeyWord = '';
let virtualKeyWord = '';
let definedOnAncestor = false;
// In the case of the source being a class, we check if it is already defined on an ancestor
if (spec.isClassType(cls)) {
definedOnAncestor = this.isMemberDefinedOnAncestor(cls, method);
}
// The method is an override if it's defined on the ancestor, or if the parent is a class and we are generating a proxy or datatype class
let overrides =
definedOnAncestor || (spec.isClassType(cls) && emitForProxyOrDatatype);
// We also inspect the jsii model to see if it overrides a class member.
if (method.overrides) {
const overrideType = this.findType(method.overrides);
if (spec.isClassType(overrideType)) {
// Overrides a class, needs overrides keyword
overrides = true;
}
}
if (overrides) {
// Add the override key word if the method is emitted for a proxy or data type or is defined on an ancestor. If
// the member is static, use the "new" keyword instead, to indicate we are intentionally hiding the ancestor
// declaration (as C# does not inherit statics, they can be hidden but not overridden). The "new" keyword is
// optional in this context, but helps clarify intention.
overrideKeyWord = method.static ? 'new ' : 'override ';
} else if (
!method.static &&
(method.abstract || !definedOnAncestor) &&
!emitForProxyOrDatatype
) {
// Add the virtual key word if the method is abstract or not defined on an ancestor and we are NOT generating a proxy or datatype class
// Methods should always be virtual when possible
virtualKeyWord = 'virtual ';
}
const access = this.renderAccessLevel(method);
const methodName = this.nameutils.convertMethodName(method.name);
const isOptional = method.returns && method.returns.optional ? '?' : '';
const signature = `${returnType}${isOptional} ${methodName}(${this.renderMethodParameters(
method,
)})`;
this.dotnetDocGenerator.emitDocs(method, {
api: 'member',
fqn: definingType.fqn,
memberName: method.name,
});
this.dotnetRuntimeGenerator.emitAttributesForMethod(
cls,
method /*, emitForProxyOrDatatype*/,
);
if (method.abstract) {
this.code.line(`${access} ${overrideKeyWord}abstract ${signature};`);
this.code.line();
} else {
this.code.openBlock(
`${access} ${staticKeyWord}${overrideKeyWord}${virtualKeyWord}${signature}`,
);
this.emitUnionParameterValdation(
(
this.reflectAssembly.findType(cls.fqn) as
| reflect.ClassType
| reflect.InterfaceType
).allMethods.find((m) => m.name === method.name)!.parameters,
);
this.code.line(
this.dotnetRuntimeGenerator.createInvokeMethodIdentifier(
method,
cls as spec.ClassType,
),
);
this.code.closeBlock();
}
}