Skip to content

[Hosting] Register ImageSource services as KeyedServices#19641

Closed
mdh1418 wants to merge 33 commits intodotnet:net9.0from
mdh1418:register_keyed_image_source_services
Closed

[Hosting] Register ImageSource services as KeyedServices#19641
mdh1418 wants to merge 33 commits intodotnet:net9.0from
mdh1418:register_keyed_image_source_services

Conversation

@mdh1418
Copy link
Copy Markdown
Member

@mdh1418 mdh1418 commented Jan 1, 2024

Description of Change

This PR aims to overhaul the ImageSourceServiceProvider-based ImageSource Service registration setup in favor of leveraging Keyed Services introduced in .NET 8 to achieve a more trimmer friendly solution.

ImageSourceServiceProvider was initially introduced to be able to retrieve various derivations of ImageSourceService of which each would interact with its own derivation of an ImageSource (i.e. FileImageSourceService : ImageSourceService, IImageSourceService<IFileImageSource>). Thus, for the ImageSourceServiceProvider to grab these services, it would need to resolve an ImageSource to the corresponding IImagesourceService<> generic that the service had been registered with via trimming unfriendly System.Type.MakeGenericType

public IImageSourceService? GetImageSourceService(Type imageSource) =>
(IImageSourceService?)GetService(GetImageSourceServiceType(imageSource));
public Type GetImageSourceServiceType(Type imageSource) =>
_serviceCache.GetOrAdd(imageSource, type =>
{
var genericConcreteType = ImageSourceServiceType.MakeGenericType(type);
if (genericConcreteType != null && GetServiceDescriptor(genericConcreteType) != null)
return genericConcreteType;
return ImageSourceServiceType.MakeGenericType(GetImageSourceType(type));
});
public Type GetImageSourceType(Type imageSource) =>
_imageSourceCache.GetOrAdd(imageSource, CreateImageSourceTypeCacheEntry);
Type CreateImageSourceTypeCacheEntry(Type type)
{
if (type.IsInterface)
{
if (type.GetInterface(ImageSourceInterface) != null)
return type;
}
else
{
foreach (var directInterface in type.GetInterfaces())
{
if (directInterface.GetInterface(ImageSourceInterface) != null)
return directInterface;
}
}
throw new InvalidOperationException($"Unable to find the image source type because none of the interfaces on {type.Name} were derived from {nameof(IImageSource)}.");
}
.

Instead, leveraging Keyed Services to register and retrieve each ImageSourceService with a service key such as the underlying ImageSource type IFileImageSource, renders the logic to extrapolate an IImageSourceService<> generic from an ImageSource type unnecessary (one could grab the ImageSourceService via GetRequiredKeyedService<IImageSourceService>(typeof(IFileImageSource))). As a result, the ImageSourceServices can be registered directly through the MauiApp's ServiceCollection, making the ImageSourceServiceProvider class unnecessary.

This PR overhauls the ImageSourceServiceProvider-based ImageSource Service registration setup by:

  • Registering the various ImageSource Services directly through the MauiApp's ServiceCollection
  • Replacing ImageSourceServiceProvider API calls with the corresponding GetRequiredKeyedService/GetKeyedService calls
    • Ensuring providers used to retrieve ImageSourceServices can be casted to IKeyedServiceProvider
      • Modifying MauiContext's underlying WrappedServiceProvider implements IKeyedServiceProvider
      • Modifying Public API signatures to use IKeyedServiceProvider instead of IServiceProvider
  • Removing ImageSourceServiceProvider all together
  • [WIP] Modifying tests to reflect the change in ImageSourceService registration

Issues Fixed

Fixes ImageSourceServiceProvider trimming warnings mentioned in #19397. Once this PR is merged, the number of warnings tracked by PublishNativeAOTCheckWarnings introduced in #19194 should decrease.

@ghost ghost added the community ✨ Community Contribution label Jan 1, 2024
@ghost
Copy link
Copy Markdown

ghost commented Jan 1, 2024

Hey there @mdh1418! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@simonrozsival
Copy link
Copy Markdown
Member

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@rmarinho
Copy link
Copy Markdown
Member

rmarinho commented Jan 2, 2024

Can we get a little more context about this on the PR description?

@mdh1418
Copy link
Copy Markdown
Member Author

mdh1418 commented Jan 2, 2024

@rmarinho Yes, sorry it is still a work in progress, and I haven't had time to fill out the description yet.

@mdh1418 mdh1418 changed the base branch from main to net9.0 January 2, 2024 21:20
@mdh1418 mdh1418 changed the base branch from net9.0 to main January 2, 2024 21:20
@jonathanpeppers
Copy link
Copy Markdown
Member

Can you target the net9.0 branch instead? main is for .NET 8 servicing right now.

@jonathanpeppers jonathanpeppers added legacy-area-perf Startup / Runtime performance perf/app-size Application Size / Trimming (sub: perf) and removed community ✨ Community Contribution labels Jan 3, 2024
@jonathanpeppers jonathanpeppers added this to the .NET 9 Planning milestone Jan 3, 2024
@mdh1418 mdh1418 changed the base branch from main to net9.0 January 3, 2024 15:21
@mdh1418 mdh1418 force-pushed the register_keyed_image_source_services branch from eb696b4 to d8e7c66 Compare January 3, 2024 15:21
mdh1418 added 15 commits January 5, 2024 18:12
With keyed services introduced in net8.0, register the default IImageSourceServices
as keyed services directly through the MauiApp's ServiceProvider's ServiceCollection
in preparation to obviate ImageSourceServiceProvider logic.
Tests leverage ContextStub instead of MauiContext. With ImageSourceServices
registered as keyed services, ContextStub needs to implement IKeyedServiceProvider
in order for tests to properly grab keyed image sources.
@mdh1418
Copy link
Copy Markdown
Member Author

mdh1418 commented Jan 8, 2024

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@mdh1418 mdh1418 marked this pull request as ready for review January 8, 2024 16:41
@mdh1418 mdh1418 requested a review from a team as a code owner January 8, 2024 16:41
@mdh1418 mdh1418 requested review from PureWeen, jonathanpeppers, jsuarezruiz, mattleibow, rmarinho and simonrozsival and removed request for a team January 8, 2024 16:41
Comment on lines +135 to +136
if (context.Services is not IKeyedServiceProvider provider)
throw new InvalidOperationException($"Context services {nameof(context.Services)} does not implement {nameof(IKeyedServiceProvider)}");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PureWeen can/should we change context.Services to an IKeyedServiceProvider? (it extends IServiceProvider) Then we wouldn't need to cast/throw here?

https://github.com/dotnet/runtime/blob/0823c5c2814ffad5718f06715899ef91aa84aae2/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IKeyedServiceProvider.cs#L12

The cast/throw occurs a couple places in this PR.

@mdh1418 mdh1418 marked this pull request as draft January 16, 2024 16:00
@rmarinho rmarinho deleted the branch dotnet:net9.0 January 31, 2024 11:32
@rmarinho rmarinho closed this Jan 31, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Mar 2, 2024
@Eilon Eilon added area-publishing Issues with the app packaging/publishing process (ipk/apk/msix/trimming) perf/general The issue affects performance (runtime speed, memory usage, startup time, etc.) (sub: perf) and removed legacy-area-perf Startup / Runtime performance labels May 10, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-publishing Issues with the app packaging/publishing process (ipk/apk/msix/trimming) perf/app-size Application Size / Trimming (sub: perf) perf/general The issue affects performance (runtime speed, memory usage, startup time, etc.) (sub: perf)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants