diff --git a/src/AST/Class.cs b/src/AST/Class.cs index 535236e35..d598c59e5 100644 --- a/src/AST/Class.cs +++ b/src/AST/Class.cs @@ -85,7 +85,12 @@ public class Class : DeclarationContext // True if the class is a singleton and should be accessed as such // from the generated GetInstance method. - public bool IsSingleton; + public bool KytIsSingleton; + + // True if the class should generate an action that is called from Dispose. + // This allows you to hook into the native destruction of an object from + // outside the object, which helps when using the composition pattern. + public bool KytGenerateOnDispose; // Semantic type of the class. public ClassType Type; @@ -144,7 +149,8 @@ public Class() IsUnion = false; IsFinal = false; IsPOD = false; - IsSingleton = false; + KytIsSingleton = false; + KytGenerateOnDispose = false; Type = ClassType.RefType; Layout = new ClassLayout(); templateParameters = new List(); diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs index f11696803..0304b082e 100644 --- a/src/Generator/Generators/CSharp/CSharpSources.cs +++ b/src/Generator/Generators/CSharp/CSharpSources.cs @@ -2301,6 +2301,13 @@ private void GenerateDisposeMethods(Class @class) } } + if (@class.KytGenerateOnDispose) + { + PushBlock(BlockKind.Field); + WriteLine("public Action OnDispose;"); + PopBlock(NewLineKind.BeforeNextBlock); + } + // Declare partial method that the partial class can implement to participate // in dispose. PushBlock(BlockKind.Method); @@ -2337,7 +2344,10 @@ private void GenerateDisposeMethods(Class @class) // // Delegate to partial method if implemented WriteLine("DisposePartial(disposing);"); - + if (@class.KytGenerateOnDispose) + { + WriteLine("OnDispose?.Invoke(disposing);"); + } var dtor = @class.Destructors.FirstOrDefault(); if (dtor != null && dtor.Access != AccessSpecifier.Private && @class.HasNonTrivialDestructor && !@class.IsAbstract) @@ -2455,7 +2465,7 @@ private void GenerateNativeConstructor(Class @class) if (@class.IsRefType) { - if(@class.IsSingleton) + if(@class.KytIsSingleton) { WriteLine($"private static {printedClass} singletonInstance;"); } @@ -2465,7 +2475,7 @@ private void GenerateNativeConstructor(Class @class) bool generateNativeToManaged = Options.GenerateNativeToManagedFor(@class); if (generateNativeToManaged) { - if (@class.IsSingleton) + if (@class.KytIsSingleton) { WriteLines($@" internal static{(@new ? " new" : string.Empty)} {printedClass} __GetOrCreateInstance({TypePrinter.IntPtrType} native, bool saveInstance = false, bool skipVTables = false) @@ -2506,7 +2516,7 @@ private void GenerateNativeConstructor(Class @class) { @new = @class.HasBase && HasVirtualTables(@class.Bases.First().Class); - if (@class.IsSingleton) + if (@class.KytIsSingleton) { WriteLines($@" internal static{(@new ? " new" : string.Empty)} {printedClass} __GetInstance({TypePrinter.IntPtrType} native)