File: Hosting\Effects\AppHostBuilderExtensions.cs
Web Access
Project: src\src\Controls\src\Core\Controls.Core.csproj (Microsoft.Maui.Controls)
#nullable disable
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Maui.Controls.Internals;
using Microsoft.Maui.Controls.Platform;
using Microsoft.Maui.Hosting;
 
namespace Microsoft.Maui.Controls.Hosting
{
	internal static class CompatibilityCheck
	{
		// This code is currently here because RelativeLayout is still in Controls
		// I ran into issues with XamlC and moving RelativeLayout to compatibility
		// If that issue gets resolved then we can move this back to Compatibility
		static bool _compatibilityEnabled = false;
		internal static void CheckForCompatibility([CallerMemberName] string memberName = "")
		{
			if (!_compatibilityEnabled)
			{
				throw new InvalidOperationException(
					$"{memberName} is currently not enabled. To enable compatibility features you will need to call add `builder.UseMauiCompatibility()`.\n\n" +
					"MauiApp\n" +
					"	.CreateBuilder()\n" +
					"	.UseMauiApp<TApp>()\n" +
					"	.UseMauiCompatibility();\n"
					);
			}
		}
 
		internal static void ResetCompatibilityCheck() =>
			_compatibilityEnabled = false;
 
		internal static void UseCompatibility() =>
			_compatibilityEnabled = true;
	}
 
	public static partial class AppHostBuilderExtensions
	{
		public static MauiAppBuilder ConfigureEffects(this MauiAppBuilder builder, Action<IEffectsBuilder> configureDelegate)
		{
			builder.Services.TryAddSingleton(svc => new EffectsFactory(svc.GetServices<EffectsRegistration>()));
			if (configureDelegate != null)
			{
				builder.Services.AddSingleton<EffectsRegistration>(new EffectsRegistration(configureDelegate));
			}
 
			return builder;
		}
	}
 
	internal class EffectsRegistration
	{
		private readonly Action<IEffectsBuilder> _registerEffects;
 
		public EffectsRegistration(Action<IEffectsBuilder> registerEffects)
		{
			_registerEffects = registerEffects;
		}
 
		internal void AddEffects(IEffectsBuilder effects)
		{
			_registerEffects(effects);
		}
	}
 
	internal class EffectCollectionBuilder : IEffectsBuilder
	{
		internal Dictionary<Type, Func<PlatformEffect>> RegisteredEffects { get; } = new Dictionary<Type, Func<PlatformEffect>>();
 
		public IEffectsBuilder Add<TEffect, TPlatformEffect>()
			where TEffect : RoutingEffect
			where TPlatformEffect : PlatformEffect, new()
		{
			RegisteredEffects.Add(typeof(TEffect), () =>
			{
				if (DependencyResolver.Resolve(typeof(TPlatformEffect)) is TPlatformEffect pe)
					return pe;
 
				return new TPlatformEffect();
			});
			return this;
		}
 
		public IEffectsBuilder Add(
			Type TEffect,
			[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type TPlatformEffect)
		{
			RegisteredEffects.Add(TEffect, () =>
			{
				return (PlatformEffect)DependencyResolver.ResolveOrCreate(TPlatformEffect);
			});
 
			return this;
		}
	}
 
	internal class EffectsFactory
	{
		private readonly Dictionary<Type, Func<PlatformEffect>> _registeredEffects;
 
		public EffectsFactory(IEnumerable<EffectsRegistration> effectsRegistrations)
		{
			if (effectsRegistrations != null)
			{
				var effectsBuilder = new EffectCollectionBuilder();
				foreach (var effectRegistration in effectsRegistrations)
				{
					effectRegistration.AddEffects(effectsBuilder);
				}
				_registeredEffects = effectsBuilder.RegisteredEffects;
			}
		}
 
		internal PlatformEffect CreateEffect(Effect fromEffect)
		{
			if (_registeredEffects != null && _registeredEffects.TryGetValue(fromEffect.GetType(), out Func<PlatformEffect> effectType))
			{
				return effectType();
			}
 
			return null;
		}
	}
}