| | | 1 | | using NexusLabs.Needlr.Injection.Reflection.Loaders; |
| | | 2 | | using NexusLabs.Needlr.Injection.Reflection.PluginFactories; |
| | | 3 | | using NexusLabs.Needlr.Injection.Reflection.TypeFilterers; |
| | | 4 | | using NexusLabs.Needlr.Injection.Reflection.TypeRegistrars; |
| | | 5 | | |
| | | 6 | | using System.Diagnostics.CodeAnalysis; |
| | | 7 | | |
| | | 8 | | namespace NexusLabs.Needlr.Injection.Reflection; |
| | | 9 | | |
| | | 10 | | /// <summary> |
| | | 11 | | /// Extension methods for configuring <see cref="Syringe"/> with reflection-based components. |
| | | 12 | | /// </summary> |
| | | 13 | | /// <remarks> |
| | | 14 | | /// <para> |
| | | 15 | | /// These extensions enable runtime reflection-based type discovery and registration. |
| | | 16 | | /// Use these when you need dynamic assembly loading or when source generation is not available. |
| | | 17 | | /// </para> |
| | | 18 | | /// <para> |
| | | 19 | | /// For AOT/trimming compatibility, use <c>NexusLabs.Needlr.Injection.SourceGen</c> instead. |
| | | 20 | | /// </para> |
| | | 21 | | /// </remarks> |
| | | 22 | | public static class SyringeReflectionExtensions |
| | | 23 | | { |
| | | 24 | | /// <summary> |
| | | 25 | | /// Configures the syringe to use all reflection-based components. |
| | | 26 | | /// </summary> |
| | | 27 | | /// <remarks> |
| | | 28 | | /// This sets the type registrar, type filterer, plugin factory, and assembly provider |
| | | 29 | | /// to their reflection-based implementations. Not compatible with AOT/trimming. |
| | | 30 | | /// </remarks> |
| | | 31 | | /// <param name="syringe">The syringe to configure.</param> |
| | | 32 | | /// <returns>A configured syringe ready for further configuration and building.</returns> |
| | | 33 | | [RequiresUnreferencedCode("Enables reflection-based type discovery. Not compatible with AOT/trimming.")] |
| | | 34 | | public static ConfiguredSyringe UsingReflection(this Syringe syringe) |
| | | 35 | | { |
| | 329 | 36 | | ArgumentNullException.ThrowIfNull(syringe); |
| | 329 | 37 | | return new ConfiguredSyringe(syringe) with |
| | 329 | 38 | | { |
| | 329 | 39 | | TypeRegistrar = new ReflectionTypeRegistrar(), |
| | 329 | 40 | | TypeFilterer = new ReflectionTypeFilterer(), |
| | 329 | 41 | | PluginFactory = new ReflectionPluginFactory(), |
| | 329 | 42 | | AssemblyProvider = new AssemblyProviderBuilder().Build(), |
| | 329 | 43 | | ServiceProviderBuilderFactory = (populator, assemblyProvider, additionalAssemblies) => |
| | 288 | 44 | | new ReflectionServiceProviderBuilder(populator, assemblyProvider, additionalAssemblies) |
| | 329 | 45 | | }; |
| | | 46 | | } |
| | | 47 | | |
| | | 48 | | /// <summary> |
| | | 49 | | /// Configures the syringe to use the reflection-based type registrar. |
| | | 50 | | /// </summary> |
| | | 51 | | /// <param name="syringe">The configured syringe to update.</param> |
| | | 52 | | /// <returns>A new configured syringe instance.</returns> |
| | | 53 | | [RequiresUnreferencedCode("ReflectionTypeRegistrar uses reflection to discover types.")] |
| | | 54 | | public static ConfiguredSyringe UsingReflectionTypeRegistrar(this ConfiguredSyringe syringe) |
| | | 55 | | { |
| | 1 | 56 | | ArgumentNullException.ThrowIfNull(syringe); |
| | 1 | 57 | | return syringe.UsingTypeRegistrar(new ReflectionTypeRegistrar()); |
| | | 58 | | } |
| | | 59 | | |
| | | 60 | | /// <summary> |
| | | 61 | | /// Configures the syringe to use the reflection-based type filterer. |
| | | 62 | | /// </summary> |
| | | 63 | | /// <param name="syringe">The configured syringe to update.</param> |
| | | 64 | | /// <returns>A new configured syringe instance.</returns> |
| | | 65 | | [RequiresUnreferencedCode("ReflectionTypeFilterer uses reflection to analyze constructors.")] |
| | | 66 | | public static ConfiguredSyringe UsingReflectionTypeFilterer(this ConfiguredSyringe syringe) |
| | | 67 | | { |
| | 1 | 68 | | ArgumentNullException.ThrowIfNull(syringe); |
| | 1 | 69 | | return syringe.UsingTypeFilterer(new ReflectionTypeFilterer()); |
| | | 70 | | } |
| | | 71 | | |
| | | 72 | | /// <summary> |
| | | 73 | | /// Configures the syringe to use the reflection-based plugin factory. |
| | | 74 | | /// </summary> |
| | | 75 | | /// <param name="syringe">The configured syringe to update.</param> |
| | | 76 | | /// <returns>A new configured syringe instance.</returns> |
| | | 77 | | [RequiresUnreferencedCode("ReflectionPluginFactory uses reflection to discover and instantiate plugins.")] |
| | | 78 | | public static ConfiguredSyringe UsingReflectionPluginFactory(this ConfiguredSyringe syringe) |
| | | 79 | | { |
| | 1 | 80 | | ArgumentNullException.ThrowIfNull(syringe); |
| | 1 | 81 | | return syringe.UsingPluginFactory(new ReflectionPluginFactory()); |
| | | 82 | | } |
| | | 83 | | |
| | | 84 | | /// <summary> |
| | | 85 | | /// Configures the syringe to use the reflection-based assembly provider. |
| | | 86 | | /// </summary> |
| | | 87 | | /// <param name="syringe">The configured syringe to update.</param> |
| | | 88 | | /// <returns>A new configured syringe instance.</returns> |
| | | 89 | | [RequiresUnreferencedCode("AssemblyProviderBuilder uses reflection to load assemblies.")] |
| | | 90 | | public static ConfiguredSyringe UsingReflectionAssemblyProvider(this ConfiguredSyringe syringe) |
| | | 91 | | { |
| | 1 | 92 | | ArgumentNullException.ThrowIfNull(syringe); |
| | 1 | 93 | | return syringe.UsingAssemblyProvider(new AssemblyProviderBuilder().Build()); |
| | | 94 | | } |
| | | 95 | | |
| | | 96 | | /// <summary> |
| | | 97 | | /// Configures the syringe to use a custom assembly provider built with the builder pattern. |
| | | 98 | | /// </summary> |
| | | 99 | | /// <param name="syringe">The configured syringe to update.</param> |
| | | 100 | | /// <param name="configure">A function to configure the assembly provider builder.</param> |
| | | 101 | | /// <returns>A new configured syringe instance.</returns> |
| | | 102 | | [RequiresUnreferencedCode("AssemblyProviderBuilder uses reflection to load assemblies.")] |
| | | 103 | | public static ConfiguredSyringe UsingAssemblyProvider( |
| | | 104 | | this ConfiguredSyringe syringe, |
| | | 105 | | Func<IAssemblyProviderBuilder, IAssemblyProvider> configure) |
| | | 106 | | { |
| | 22 | 107 | | ArgumentNullException.ThrowIfNull(syringe); |
| | 22 | 108 | | ArgumentNullException.ThrowIfNull(configure); |
| | | 109 | | |
| | 22 | 110 | | var provider = configure(new AssemblyProviderBuilder()); |
| | 22 | 111 | | return syringe.UsingAssemblyProvider(provider); |
| | | 112 | | } |
| | | 113 | | |
| | | 114 | | /// <summary> |
| | | 115 | | /// Configures a handler to be invoked when reflection-based components are used as fallback. |
| | | 116 | | /// </summary> |
| | | 117 | | /// <param name="syringe">The configured syringe to update.</param> |
| | | 118 | | /// <param name="handler">The handler to invoke when reflection fallback occurs.</param> |
| | | 119 | | /// <returns>A new configured syringe instance.</returns> |
| | | 120 | | public static ConfiguredSyringe WithReflectionFallbackHandler( |
| | | 121 | | this ConfiguredSyringe syringe, |
| | | 122 | | Action<ReflectionFallbackContext> handler) |
| | | 123 | | { |
| | 6 | 124 | | ArgumentNullException.ThrowIfNull(syringe); |
| | 6 | 125 | | ArgumentNullException.ThrowIfNull(handler); |
| | | 126 | | |
| | | 127 | | // Store the handler for use by Bundle's fallback logic |
| | | 128 | | // The base Syringe doesn't have this property, so we use a callback pattern |
| | 5 | 129 | | return syringe.UsingPostPluginRegistrationCallback(_ => |
| | 5 | 130 | | { |
| | 5 | 131 | | // This is a placeholder - the actual fallback handling is in Bundle |
| | 5 | 132 | | }); |
| | | 133 | | } |
| | | 134 | | } |