diff --git a/Telegrator.Hosting/Providers/HostHandlersProvider.cs b/Telegrator.Hosting/Providers/HostHandlersProvider.cs index 167737b..8204fd2 100644 --- a/Telegrator.Hosting/Providers/HostHandlersProvider.cs +++ b/Telegrator.Hosting/Providers/HostHandlersProvider.cs @@ -49,6 +49,7 @@ namespace Telegrator.Hosting.Providers if (handlerInstance is not UpdateHandlerBase updateHandler) throw new InvalidOperationException("Failed to resolve " + descriptor.HandlerType + " as UpdateHandlerBase"); + descriptor.LazyInitialization?.Invoke(updateHandler); updateHandler.LifetimeToken.OnLifetimeEnded += _ => scope.Dispose(); return updateHandler; } diff --git a/Telegrator.sln b/Telegrator.sln index 0f9d08f..84f7362 100644 --- a/Telegrator.sln +++ b/Telegrator.sln @@ -18,6 +18,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegrator.Analyzers", "Telegrator.Analyzers\Telegrator.Analyzers.csproj", "{8B6A32EA-ECF7-4CAB-A1E5-2392063C986D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegrator.ConsoleHost", "..\Telegram.Reactive.TestApps\Telegrator.ConsoleHost\Telegrator.ConsoleHost.csproj", "{78691EF7-6009-3BB1-C90D-1D1D95442041}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AnalyzersDebug|Any CPU = AnalyzersDebug|Any CPU @@ -55,6 +57,12 @@ Global {8B6A32EA-ECF7-4CAB-A1E5-2392063C986D}.Debug|Any CPU.Build.0 = Debug|Any CPU {8B6A32EA-ECF7-4CAB-A1E5-2392063C986D}.Release|Any CPU.ActiveCfg = Release|Any CPU {8B6A32EA-ECF7-4CAB-A1E5-2392063C986D}.Release|Any CPU.Build.0 = Release|Any CPU + {78691EF7-6009-3BB1-C90D-1D1D95442041}.AnalyzersDebug|Any CPU.ActiveCfg = AnalyzersDebug|Any CPU + {78691EF7-6009-3BB1-C90D-1D1D95442041}.AnalyzersDebug|Any CPU.Build.0 = AnalyzersDebug|Any CPU + {78691EF7-6009-3BB1-C90D-1D1D95442041}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78691EF7-6009-3BB1-C90D-1D1D95442041}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78691EF7-6009-3BB1-C90D-1D1D95442041}.Release|Any CPU.ActiveCfg = Release|Any CPU + {78691EF7-6009-3BB1-C90D-1D1D95442041}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Telegrator/Handlers/Components/BranchingUpdateHandler.cs b/Telegrator/Handlers/Components/BranchingUpdateHandler.cs index 0352127..a8b6108 100644 --- a/Telegrator/Handlers/Components/BranchingUpdateHandler.cs +++ b/Telegrator/Handlers/Components/BranchingUpdateHandler.cs @@ -43,14 +43,6 @@ namespace Telegrator.Handlers.Components protected BranchingUpdateHandler(UpdateType handlingUpdateType) : base(handlingUpdateType) { } - /// - /// Initializes a new instance of the class with a specific branch method. - /// - /// The type of update this handler processes. - /// The specific branch method to execute. - protected BranchingUpdateHandler(UpdateType handlingUpdateType, MethodInfo branch) - : base(handlingUpdateType) => branchMethodInfo = branch; - /// /// Describes all handler branches in this class. /// @@ -92,7 +84,7 @@ namespace Telegrator.Handlers.Components { handlerAttribute = HandlerInspector.GetHandlerAttribute(branch); } - finally + catch { _ = 0xBAD + 0xC0DE; } @@ -105,7 +97,7 @@ namespace Telegrator.Handlers.Components HandlerInspector.GetStateKeeperAttribute(branch), branchFiltersList.ToArray()); - return new HandlerBranchDescriptor(branch, HandlingUpdateType, handlerAttribute.GetIndexer(), filtersSet); + return new HandlerBranchDescriptor(thisType, branch, HandlingUpdateType, handlerAttribute.GetIndexer(), filtersSet); } /// @@ -160,15 +152,15 @@ namespace Telegrator.Handlers.Components private class HandlerBranchDescriptor : HandlerDescriptor { - public HandlerBranchDescriptor(MethodInfo method, UpdateType updateType, DescriptorIndexer indexer, DescriptorFiltersSet filters) - : base(DescriptorType.General, method.DeclaringType, updateType, indexer, filters) + public HandlerBranchDescriptor(Type decalringType, MethodInfo method, UpdateType updateType, DescriptorIndexer indexer, DescriptorFiltersSet filters) : base(DescriptorType.General, decalringType, updateType, indexer, filters) { - DisplayString = string.Format("{0}+{1}", method.DeclaringType.Name, method.Name); - InstanceFactory = () => + DisplayString = HandlerInspector.GetDisplayName(method) ?? string.Format("{0}+{1}", method.DeclaringType.Name, method.Name); + LazyInitialization = handler => { - BranchingUpdateHandler handler = (BranchingUpdateHandler)Activator.CreateInstance(method.DeclaringType); - handler.branchMethodInfo = method; - return handler; + if (handler is not BranchingUpdateHandler brancher) + throw new InvalidDataException(); + + brancher.branchMethodInfo = method; }; } } diff --git a/Telegrator/MadiatorCore/Descriptors/HandlerDescriptor.cs b/Telegrator/MadiatorCore/Descriptors/HandlerDescriptor.cs index 8de3142..6ceb42a 100644 --- a/Telegrator/MadiatorCore/Descriptors/HandlerDescriptor.cs +++ b/Telegrator/MadiatorCore/Descriptors/HandlerDescriptor.cs @@ -97,7 +97,7 @@ namespace Telegrator.MadiatorCore.Descriptors public Func? InstanceFactory { get; - set; + private set; } /// @@ -118,6 +118,15 @@ namespace Telegrator.MadiatorCore.Descriptors set; } + /// + /// Gets or sets a function for 'lazy' handlers initialization + /// + public Action? LazyInitialization + { + get; + set; + } + /// /// Initializes a new instance of the class with the specified descriptor type and handler type. /// Automatically inspects the handler type to extract attributes, filters, and configuration. diff --git a/Telegrator/Providers/HandlersProvider.cs b/Telegrator/Providers/HandlersProvider.cs index 73dbf79..fed5f5f 100644 --- a/Telegrator/Providers/HandlersProvider.cs +++ b/Telegrator/Providers/HandlersProvider.cs @@ -1,4 +1,5 @@ using System.Collections.ObjectModel; +using System.Runtime.CompilerServices; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; using Telegrator.Configuration; @@ -60,29 +61,32 @@ namespace Telegrator.Providers public virtual UpdateHandlerBase GetHandlerInstance(HandlerDescriptor descriptor, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); - switch (descriptor.Type) - { - case DescriptorType.Implicit: - case DescriptorType.Singleton: - { - return descriptor.SingletonInstance ??= (descriptor.InstanceFactory != null - ? descriptor.SingletonInstance = descriptor.InstanceFactory.Invoke() - : descriptor.SingletonInstance = (UpdateHandlerBase)Activator.CreateInstance(descriptor.HandlerType)); - } + bool useSingleton = UseSingleton(descriptor); - case DescriptorType.Keyed: - case DescriptorType.General: - { - return descriptor.InstanceFactory == null - ? (UpdateHandlerBase)Activator.CreateInstance(descriptor.HandlerType) - : descriptor.InstanceFactory.Invoke(); - } + if (useSingleton && descriptor.SingletonInstance != null) + return descriptor.SingletonInstance; - default: - throw new Exception(); - } + UpdateHandlerBase instance = GetHandlerInstanceInternal(descriptor); + descriptor.SingletonInstance = useSingleton ? instance : null; + descriptor.LazyInitialization?.Invoke(instance); + return instance; } + private static UpdateHandlerBase GetHandlerInstanceInternal(HandlerDescriptor descriptor) + { + if (descriptor.InstanceFactory != null) + return descriptor.InstanceFactory.Invoke(); + + return (UpdateHandlerBase)Activator.CreateInstance(descriptor.HandlerType); + } + + private static bool UseSingleton(HandlerDescriptor descriptor) => descriptor.Type switch + { + DescriptorType.General or DescriptorType.Keyed => false, + DescriptorType.Implicit or DescriptorType.Singleton => true, + _ => throw new Exception() + }; + /// public virtual bool TryGetDescriptorList(UpdateType updateType, out HandlerDescriptorList? list) {