diff options
author | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 13:02:25 -0700 |
---|---|---|
committer | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 16:13:41 -0700 |
commit | 17fdde66d94155fc62a034fa6658995bef6fd6e5 (patch) | |
tree | b5e5073a2a7b15cdbe826faa5c763e270a505729 /Xamarin.Forms.Core/Registrar.cs | |
download | xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.gz xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.bz2 xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.zip |
Initial import
Diffstat (limited to 'Xamarin.Forms.Core/Registrar.cs')
-rw-r--r-- | Xamarin.Forms.Core/Registrar.cs | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core/Registrar.cs b/Xamarin.Forms.Core/Registrar.cs new file mode 100644 index 00000000..92c2e533 --- /dev/null +++ b/Xamarin.Forms.Core/Registrar.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace Xamarin.Forms +{ + internal class Registrar<TRegistrable> where TRegistrable : class + { + readonly Dictionary<Type, Type> _handlers = new Dictionary<Type, Type>(); + + public void Register(Type tview, Type trender) + { + _handlers[tview] = trender; + } + + internal TRegistrable GetHandler(Type type) + { + Type handlerType = GetHandlerType(type); + if (handlerType == null) + return null; + + object handler = Activator.CreateInstance(handlerType); + return (TRegistrable)handler; + } + + internal TOut GetHandler<TOut>(Type type) where TOut : TRegistrable + { + return (TOut)GetHandler(type); + } + + internal Type GetHandlerType(Type viewType) + { + Type type = LookupHandlerType(viewType); + if (type != null) + return type; + + // lazy load render-view association with RenderWithAttribute (as opposed to using ExportRenderer) + // TODO: change Registrar to a LazyImmutableDictionary and pass this logic to ctor as a delegate. + var attribute = viewType.GetTypeInfo().GetCustomAttribute<RenderWithAttribute>(); + if (attribute == null) + return null; + type = attribute.Type; + + if (type.Name.StartsWith("_")) + { + // TODO: Remove attribute2 once renderer names have been unified across all platforms + var attribute2 = type.GetTypeInfo().GetCustomAttribute<RenderWithAttribute>(); + if (attribute2 != null) + type = attribute2.Type; + + if (type.Name.StartsWith("_")) + { + //var attrs = type.GetTypeInfo ().GetCustomAttributes ().ToArray (); + return null; + } + } + + Register(viewType, type); + return LookupHandlerType(viewType); + } + + Type LookupHandlerType(Type viewType) + { + Type type = viewType; + + while (true) + { + if (_handlers.ContainsKey(type)) + return _handlers[type]; + + type = type.GetTypeInfo().BaseType; + if (type == null) + break; + } + + return null; + } + } + + internal static class Registrar + { + static Registrar() + { + Registered = new Registrar<IRegisterable>(); + } + + internal static Dictionary<string, Type> Effects { get; } = new Dictionary<string, Type>(); + + internal static IEnumerable<Assembly> ExtraAssemblies { get; set; } + + internal static Registrar<IRegisterable> Registered { get; } + + internal static void RegisterAll(Type[] attrTypes) + { + Assembly[] assemblies = Device.GetAssemblies(); + if (ExtraAssemblies != null) + { + assemblies = assemblies.Union(ExtraAssemblies).ToArray(); + } + + Assembly defaultRendererAssembly = Device.PlatformServices.GetType().GetTypeInfo().Assembly; + int indexOfExecuting = Array.IndexOf(assemblies, defaultRendererAssembly); + + if (indexOfExecuting > 0) + { + assemblies[indexOfExecuting] = assemblies[0]; + assemblies[0] = defaultRendererAssembly; + } + + // Don't use LINQ for performance reasons + // Naive implementation can easily take over a second to run + foreach (Assembly assembly in assemblies) + { + foreach (Type attrType in attrTypes) + { + Attribute[] attributes = assembly.GetCustomAttributes(attrType).ToArray(); + if (attributes.Length == 0) + continue; + + foreach (HandlerAttribute attribute in attributes) + { + if (attribute.ShouldRegister()) + Registered.Register(attribute.HandlerType, attribute.TargetType); + } + } + + string resolutionName = assembly.FullName; + var resolutionNameAttribute = (ResolutionGroupNameAttribute)assembly.GetCustomAttribute(typeof(ResolutionGroupNameAttribute)); + if (resolutionNameAttribute != null) + { + resolutionName = resolutionNameAttribute.ShortName; + } + + Attribute[] effectAttributes = assembly.GetCustomAttributes(typeof(ExportEffectAttribute)).ToArray(); + if (effectAttributes.Length > 0) + { + foreach (Attribute attribute in effectAttributes) + { + var effect = (ExportEffectAttribute)attribute; + Effects.Add(resolutionName + "." + effect.Id, effect.Type); + } + } + } + } + } +}
\ No newline at end of file |