| File: Hosting\Internal\RegisteredHandlerServiceTypeSet.cs | Web Access |
| Project: src\src\Core\src\Core.csproj (Microsoft.Maui) |
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; namespace Microsoft.Maui.Hosting.Internal { internal sealed class RegisteredHandlerServiceTypeSet { private static readonly ConcurrentDictionary<IMauiHandlersCollection, RegisteredHandlerServiceTypeSet> s_instances = new(); internal static RegisteredHandlerServiceTypeSet GetInstance(IMauiHandlersCollection collection) => s_instances.GetOrAdd(collection, static _ => new RegisteredHandlerServiceTypeSet()); private readonly HashSet<Type> _concreteHandlerServiceTypeSet = new(); private readonly HashSet<Type> _interfaceHandlerServiceTypeSet = new(); public void Add(Type virtualViewType) { if (virtualViewType.IsInterface) { _interfaceHandlerServiceTypeSet.Add(virtualViewType); } else { _concreteHandlerServiceTypeSet.Add(virtualViewType); } } public Type ResolveVirtualViewToRegisteredHandlerServiceType(Type type) { Debug.Assert(typeof(IElement).IsAssignableFrom(type)); if (_concreteHandlerServiceTypeSet.Contains(type) || _interfaceHandlerServiceTypeSet.Contains(type)) { return type; } return ResolveVirtualViewFromTypeSet(type, _concreteHandlerServiceTypeSet) ?? ResolveVirtualViewFromTypeSet(type, _interfaceHandlerServiceTypeSet) ?? throw new HandlerNotFoundException($"Unable to find a {nameof(IElementHandler)} corresponding to {type}. Please register a handler for {type} using `Microsoft.Maui.Hosting.MauiHandlersCollectionExtensions.AddHandler` or `Microsoft.Maui.Hosting.MauiHandlersCollectionExtensions.TryAddHandler`"); } private static Type? ResolveVirtualViewFromTypeSet(Type type, HashSet<Type> set) { Type? bestVirtualViewHandlerServiceType = null; foreach (Type registeredViewHandlerServiceType in set) { if (registeredViewHandlerServiceType.IsAssignableFrom(type)) { if (bestVirtualViewHandlerServiceType is null || bestVirtualViewHandlerServiceType.IsAssignableFrom(registeredViewHandlerServiceType)) { bestVirtualViewHandlerServiceType = registeredViewHandlerServiceType; } else if (!registeredViewHandlerServiceType.IsAssignableFrom(bestVirtualViewHandlerServiceType)) { // This exception can be thrown when the Element implements two interfaces that aren't derived from each other // which both have a registered image source service to them. // For example, consider this setup: // class MyElement : ILargeElement, IVisibleElement { ... } // // handlersCollection.AddHandler<ILargeElement, LargeElementHandler>(); // handlersCollection.AddHandler<IVisibleElement, VisibleElementHandler>(); // // var handler = Handler.GetHandler(typeof(MyElement)); // ambiguous match: both LargeElementHandler and VisibleElementHandler are registered for MyImageSource throw new InvalidOperationException($"Unable to find a single {nameof(IElementHandler)} corresponding to {type}. There is an ambiguous match between {bestVirtualViewHandlerServiceType} and {registeredViewHandlerServiceType}."); } } } return bestVirtualViewHandlerServiceType; } } }