diff --git a/src/JasperFx/IServiceContainer.cs b/src/JasperFx/IServiceContainer.cs index fa21cba..c554066 100644 --- a/src/JasperFx/IServiceContainer.cs +++ b/src/JasperFx/IServiceContainer.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using JasperFx.CodeGeneration.Frames; using Microsoft.Extensions.DependencyInjection; @@ -25,7 +26,9 @@ public interface IServiceContainer /// /// /// - T QuickBuild(); + [RequiresUnreferencedCode("QuickBuild reflects over T's public constructors and resolves [FromKeyedServices] parameters by closing IFinder via CloseAndBuildAs.")] + [RequiresDynamicCode("CloseAndBuildAs uses MakeGenericType + Activator.CreateInstance on IFinder.")] + T QuickBuild<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(); /// /// Polyfill to make IServiceProvider work like Lamar's ability @@ -34,8 +37,10 @@ public interface IServiceContainer /// /// /// - object QuickBuild(Type concreteType); - + [RequiresUnreferencedCode("QuickBuild reflects over concreteType's public constructors and resolves [FromKeyedServices] parameters by closing IFinder via CloseAndBuildAs.")] + [RequiresDynamicCode("CloseAndBuildAs uses MakeGenericType + Activator.CreateInstance on IFinder.")] + object QuickBuild([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type concreteType); + IServiceProvider Services { get; } T GetInstance(); IReadOnlyList GetAllInstances(); diff --git a/src/JasperFx/ServiceContainer.cs b/src/JasperFx/ServiceContainer.cs index 666f116..1c19c40 100644 --- a/src/JasperFx/ServiceContainer.cs +++ b/src/JasperFx/ServiceContainer.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using ImTools; using JasperFx.CodeGeneration.Frames; using JasperFx.CodeGeneration.Services; @@ -74,6 +75,8 @@ public bool HasRegistrationFor() return DefaultFor(typeof(T)); } + [UnconditionalSuppressMessage("Trimming", "IL2067:DynamicallyAccessedMembers", + Justification = "Builds a transient self-binding ServiceDescriptor for each MethodCall.HandlerType so Wolverine can wire constructor dependencies into generated code. Handler types are reached from Wolverine's IHandlerDiscovery surface, which is itself an annotated reflective entry point — handler types preserve their public constructors transitively, and a missing public ctor surfaces as the explicit NotSupportedException below rather than as a silent runtime failure.")] public IEnumerable TryCreateConstructorFrames(IEnumerable calls) { if (calls.All(x => x.Method.IsStatic)) return new List(); @@ -206,6 +209,8 @@ public static bool IsEnumerable(Type type) return false; } + [UnconditionalSuppressMessage("Trimming", "IL2067:DynamicallyAccessedMembers", + Justification = "The IsPublic + IsConcrete branch below auto-registers a self-binding ServiceDescriptor for public concrete types that weren't explicitly registered. Public concrete types reached via the family lookup either come from typeof(T) (compiler-preserved) or from user-supplied registrations whose constructors the user must keep alive. A missing public ctor at activation time surfaces from ConstructorPlan.TryBuildPlan as an InvalidPlan, not a silent failure.")] private ServiceFamily findFamily(Type serviceType) { if (_families.TryFind(serviceType, out var family)) return family; @@ -287,7 +292,7 @@ public IReadOnlyList FindAll(Type serviceType, List PlanFor(descriptor, trail)).ToArray(); } - public object BuildFromType(Type concreteType) + public object BuildFromType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type concreteType) { var constructor = concreteType.GetConstructors().Single(); var dependencies = constructor.GetParameters().Select(x => _provider.GetService(x.ParameterType)).ToArray(); @@ -306,11 +311,13 @@ public bool HasMultiplesOf(Type variableType) /// /// /// - public T QuickBuild() + [RequiresUnreferencedCode("QuickBuild reflects over T's public constructors and resolves [FromKeyedServices] parameters by closing IFinder via CloseAndBuildAs. The trimmer may remove types reached only through that closure.")] + [RequiresDynamicCode("CloseAndBuildAs uses MakeGenericType + Activator.CreateInstance on IFinder.")] + public T QuickBuild<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>() { return (T)QuickBuild(typeof(T)); } - + /// /// Polyfill to make IServiceProvider work like Lamar's ability /// to create unknown concrete types @@ -318,7 +325,9 @@ public T QuickBuild() /// /// /// - public object QuickBuild(Type concreteType) + [RequiresUnreferencedCode("QuickBuild reflects over concreteType's public constructors and resolves [FromKeyedServices] parameters by closing IFinder via CloseAndBuildAs. The trimmer may remove types reached only through that closure.")] + [RequiresDynamicCode("CloseAndBuildAs uses MakeGenericType + Activator.CreateInstance on IFinder.")] + public object QuickBuild([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type concreteType) { var constructor = concreteType.GetConstructors().Single(); var args = constructor @@ -329,7 +338,7 @@ public object QuickBuild(Type concreteType) { return typeof(IFinder<>).CloseAndBuildAs(x.ParameterType).Find(_provider, att.Key.ToString()); } - + return _provider.GetService(x.ParameterType); }) .ToArray();