/// <summary> /// Emit the PhpType finalizer. The finalizer is emitted only if there is __destruct() function /// and there is no finalizer in any base class already. The finalizer calls this.Dispose() which /// calls __destruct() function directly. /// </summary> /// <param name="phpType"></param> private static void EmitFinalizer(PhpType /*!*/ phpType) { // only if __destruct was now defined in some base class, no need to override existing definition on Finalize DRoutine basedestruct; DRoutineDesc destruct; if ((destruct = phpType.TypeDesc.GetMethod(DObject.SpecialMethodNames.Destruct)) != null && (phpType.Base == null || phpType.Base.GetMethod(DObject.SpecialMethodNames.Destruct, phpType, out basedestruct) == GetMemberResult.NotFound)) { MethodBuilder finalizer_builder = phpType.RealTypeBuilder.DefineMethod("Finalize", MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Family, typeof(void), Type.EmptyTypes); ILEmitter dil = new ILEmitter(finalizer_builder); // exact Finalize() method pattern follows: // try dil.BeginExceptionBlock(); // this.Dispose(false) dil.Emit(OpCodes.Ldarg_0); dil.Emit(OpCodes.Ldc_I4_0); dil.Emit(OpCodes.Callvirt, PHP.Core.Emit.Methods.DObject_Dispose); // finally dil.BeginFinallyBlock(); // Object.Finalize() dil.Emit(OpCodes.Ldarg_0); dil.Emit(OpCodes.Call, PHP.Core.Emit.Methods.Object_Finalize); dil.EndExceptionBlock(); dil.Emit(OpCodes.Ret); } }