From 16164132156fd799d76c8a88c11627dc66cecbf3 Mon Sep 17 00:00:00 2001 From: "E.Z. Hart" Date: Thu, 12 Jan 2017 12:22:00 -0700 Subject: [PATCH] Improve registry startup and lookup performance (#674) * Optimize search for Effect resolution name Avoid multiple collection of assemblies during startup Cache handler lookups * Handle s_initialized check inside of Initialize method --- Xamarin.Forms.Core/DependencyService.cs | 18 ++++++++++++-- Xamarin.Forms.Core/Registrar.cs | 43 ++++++++++++++++++++------------- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/Xamarin.Forms.Core/DependencyService.cs b/Xamarin.Forms.Core/DependencyService.cs index d3c4399..2e0ae05 100644 --- a/Xamarin.Forms.Core/DependencyService.cs +++ b/Xamarin.Forms.Core/DependencyService.cs @@ -14,8 +14,7 @@ namespace Xamarin.Forms public static T Get(DependencyFetchTarget fetchTarget = DependencyFetchTarget.GlobalInstance) where T : class { - if (!s_initialized) - Initialize(); + Initialize(); Type targetType = typeof(T); @@ -64,12 +63,27 @@ namespace Xamarin.Forms static void Initialize() { + if (s_initialized) + { + return; + } + Assembly[] assemblies = Device.GetAssemblies(); if (Registrar.ExtraAssemblies != null) { assemblies = assemblies.Union(Registrar.ExtraAssemblies).ToArray(); } + Initialize(assemblies); + } + + internal static void Initialize(Assembly[] assemblies) + { + if (s_initialized) + { + return; + } + Type targetAttrType = typeof(DependencyAttribute); // Don't use LINQ for performance reasons diff --git a/Xamarin.Forms.Core/Registrar.cs b/Xamarin.Forms.Core/Registrar.cs index 1224edf..0b13a61 100644 --- a/Xamarin.Forms.Core/Registrar.cs +++ b/Xamarin.Forms.Core/Registrar.cs @@ -31,15 +31,18 @@ namespace Xamarin.Forms internal Type GetHandlerType(Type viewType) { - Type type = LookupHandlerType(viewType); - if (type != null) + Type type; + if(LookupHandlerType(viewType, out type)) 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(); if (attribute == null) + { + Register(viewType, null); // Cache this result so we don't have to do GetCustomAttribute again return null; + } + type = attribute.Type; if (type.Name.StartsWith("_")) @@ -51,30 +54,33 @@ namespace Xamarin.Forms if (type.Name.StartsWith("_")) { - //var attrs = type.GetTypeInfo ().GetCustomAttributes ().ToArray (); + Register(viewType, null); // Cache this result so we don't work through this chain again return null; } } - Register(viewType, type); - return LookupHandlerType(viewType); + Register(viewType, type); // Register this so we don't have to look for the RenderWith Attibute again in the future + + return type; } - Type LookupHandlerType(Type viewType) + bool LookupHandlerType(Type viewType, out Type handlerType) { Type type = viewType; - while (true) + while (type != null) { if (_handlers.ContainsKey(type)) - return _handlers[type]; + { + handlerType = _handlers[type]; + return true; + } type = type.GetTypeInfo().BaseType; - if (type == null) - break; } - return null; + handlerType = null; + return false; } } @@ -126,15 +132,16 @@ namespace Xamarin.Forms } 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) { + var resolutionNameAttribute = (ResolutionGroupNameAttribute)assembly.GetCustomAttribute(typeof(ResolutionGroupNameAttribute)); + if (resolutionNameAttribute != null) + { + resolutionName = resolutionNameAttribute.ShortName; + } + foreach (Attribute attribute in effectAttributes) { var effect = (ExportEffectAttribute)attribute; @@ -142,6 +149,8 @@ namespace Xamarin.Forms } } } + + DependencyService.Initialize(assemblies); } } } \ No newline at end of file -- 2.7.4