Skip to content

Blazor linker strips away a method in a generated class even if the settings indicate not to. #2358

@ioancrisan

Description

@ioancrisan

Environment:

  • Windows 10 Enterprise
  • Version 10.0.19043 Build 19043
  • Visual Studio 2022 Current
  • .NET 6.0

Steps to reproduce the issue:

  • clone the repository at https://github.com/kephas-software/kephas (master)
  • open the src/Kephas.sln solution and build it.
  • start the Blazor app in Tests/Kephas.AspNetCore.Blazor.InteractiveTests/Kephas.AspNetCore.Blazor.InteractiveTests.Server
  • the application crashes while bootstrapping, the stack trace is visible in the browser console (see the attachment).
    BlazorTrimmer error

Due to the fact that it happens during bootstrap I cannot debug properly, but I managed to trace down to the code causing the issue:
\src\Kephas.Injection\Services\AppServicesAttribute.cs, line 131.
When the returned instance is returned to the caller, either the ToArray() extension method or the SelectMany() crashes.

Background:

  • the AppServicesAttribute is used to collect services for the dependency injection through a provider class, provided in the constructor and implementing the IAppServiceInfosProvider interface.
  • This attribute implements itself the IAppServiceInfosProvider interface, redirecting the interface methods to the instance created upon request.
  • The provider type is annotated with [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] in the AppServicesAttribute's constructor.
  • The provider classes are generated by an analyzer, one per assembly. The generated class where the issue occurs is listed below (can be found, after compilation, in src/Kephas.Application/obj/.generated/Kephas.Analyzers/Kephas.Analyzers.Injection.AppServicesSourceGenerator/AppServices.g.cs
#nullable enable

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;

using Kephas.Services;

[assembly: AppServices(typeof(Kephas.Injection.Generated.AppServices_Kephas_Application))]


namespace Kephas.Injection.Generated
{
#if NET6_0_OR_GREATER
   [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
#endif
   internal partial class AppServices_Kephas_Application: IAppServiceInfosProvider
   {
       IEnumerable<Type>? IAppServiceInfosProvider.GetContractDeclarationTypes(IContext? context)
       {
            yield return typeof(Kephas.Application.IAppMainLoop);
            yield return typeof(Kephas.Application.IAppManager);
            yield return typeof(Kephas.Application.IFeatureLifecycleBehavior);
            yield return typeof(Kephas.Application.IFeatureManager);
       }

       IEnumerable<ServiceDeclaration> IAppServiceInfosProvider.GetAppServices(IContext? context)
       {
            yield return new ServiceDeclaration(typeof(Kephas.Application.CommandsAppSetupHandler), typeof(Kephas.Application.IAppSetupHandler));
            yield return new ServiceDeclaration(typeof(Kephas.Application.DefaultAppMainLoop), typeof(Kephas.Application.IAppMainLoop));
            yield return new ServiceDeclaration(typeof(Kephas.Application.DefaultAppManager), typeof(Kephas.Application.IAppManager));
            yield return new ServiceDeclaration(typeof(Kephas.Application.FeatureEnabledServiceBehavior), typeof(Kephas.Services.Behaviors.IEnabledServiceBehaviorRule<, >));
            yield return new ServiceDeclaration(typeof(Kephas.Application.Interaction.InteractionFeatureLifecycleBehavior), typeof(Kephas.Application.IFeatureLifecycleBehavior));
            yield return new ServiceDeclaration(typeof(Kephas.Application.MainLoopAppLifecycleBehavior), typeof(Kephas.Application.IAppLifecycleBehavior));
            yield return new ServiceDeclaration(typeof(Kephas.Application.SetupAppLifecycleBehavior), typeof(Kephas.Application.IAppLifecycleBehavior));
            yield return new ServiceDeclaration(typeof(Kephas.Application.StartupAppLifecycleBehavior), typeof(Kephas.Application.IAppLifecycleBehavior));
       }
   }
}

From intermediary steps, which I cannot reproduce anymore, I am quite certain that the method IAppServiceInfosProvider.GetAppServices is called for AppServices_Kephas_Application. However, presumably, the object returned is missing some methods leading to the error in class-setup-vtable.c. I tried to indicate at all steps that the assemblies should not be trimmed, due to heavy use of reflection, but to no avail.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions