/// <summary> /// Called when the <c>TargetView</c> has just been loaded. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> public override async Task OnTargetViewLoadedAsync(object sender, EventArgs e) { await CompleteViewModelClosingAsync(); // Do not call base because it will create a VM. We will create the VM ourselves //base.OnTargetControlLoaded(sender, e); // Manually updating target control content wrapper here (not by content property changed event handler), // because in WinRT UserControl does NOT update bindings while InitializeComponents() method is executing, // even if the Content property was changed while InitializeComponents() running there is no triggering of a binding update. CreateViewModelWrapper(); #if NET if (!SkipSearchingForInfoBarMessageControl) { Log.Debug("Searching for an instance of the InfoBarMessageControl"); _infoBarMessageControl = TargetView.FindParentByPredicate(o => o is InfoBarMessageControl) as InfoBarMessageControl; ApiCop.UpdateRule <UnusedFeatureApiCopRule>("UserControlLogic.InfoBarMessageControl", rule => rule.IncreaseCount(_infoBarMessageControl != null, TargetViewType.FullName)); if (CreateWarningAndErrorValidatorForViewModel) { ApiCop.UpdateRule <UnusedFeatureApiCopRule>("UserControlLogic.CreateWarningAndErrorValidator", rule => rule.IncreaseCount(_infoBarMessageControl != null, TargetViewType.FullName)); } Log.Debug("Finished searching for an instance of the InfoBarMessageControl"); if (_infoBarMessageControl == null) { Log.Warning("No InfoBarMessageControl is found in the visual tree of '{0}', consider using the SkipSearchingForInfoBarMessageControl property to improve performance", GetType().Name); } } else { Log.Debug("Skipping the search for an instance of the InfoBarMessageControl"); } #endif if (!CloseViewModelOnUnloaded && (ViewModel != null)) { // Re-use view model Log.Debug("Re-using existing view model"); } if (ViewModel == null) { // Try to create view model based on data context await UpdateDataContextToUseViewModelAsync(TargetView.DataContext); } if (DisableWhenNoViewModel) { TargetView.IsEnabled = (ViewModel != null); } }
/// <summary> /// Warms up the specified types. If the <paramref name="types" /> is <c>null</c>, all types known /// in the <see cref="TypeCache" /> will be initialized. /// <para /> /// Note that it is not required to call this, but it can help to prevent an additional performance /// impact the first time a type is serialized. /// </summary> /// <param name="types">The types to warmp up. If <c>null</c>, all types will be initialized.</param> /// <param name="typesPerThread">The types per thread. If <c>-1</c>, all types will be initialized on the same thread.</param> public void Warmup(IEnumerable <Type> types, int typesPerThread = 1000) { ApiCop.UpdateRule <InitializationApiCopRule>("SerializerBase.WarmupAtStartup", x => x.SetInitializationMode(InitializationMode.Eager, GetType().GetSafeFullName(false))); if (types == null) { types = TypeCache.GetTypes(x => x.IsModelBase(), false); } var allTypes = new List <Type>(types); ParallelHelper.ExecuteInParallel(allTypes, type => { // General warmup SerializationManager.Warmup(type); // Specific (customized) warmup Warmup(type); }, typesPerThread, "warmup serializer for types"); }
/// <summary> /// Creates an instance of the specified type using the specified parameters as injection values. /// </summary> /// <param name="typeToConstruct">The type to construct.</param> /// <param name="parameters">The parameters to inject.</param> /// <param name="autoCompleteDependencies">if set to <c>true</c>, the additional dependencies will be auto completed.</param> /// <param name="preventCircularDependencies">if set to <c>true</c>, prevent circular dependencies using the <see cref="TypeRequestPath"/>.</param> /// <returns>The instantiated type using dependency injection.</returns> /// <exception cref="ArgumentNullException">The <paramref name="typeToConstruct" /> is <c>null</c>.</exception> private object CreateInstanceWithSpecifiedParameters(Type typeToConstruct, object[] parameters, bool autoCompleteDependencies, bool preventCircularDependencies = true) { Argument.IsNotNull("typeToConstruct", typeToConstruct); if (parameters == null) { parameters = new object[] { }; } lock (_serviceLocator) { TypeRequestInfo typeRequestInfo = null; try { if (preventCircularDependencies) { typeRequestInfo = new TypeRequestInfo(typeToConstruct); if (_currentTypeRequestPath == null) { _currentTypeRequestPath = new TypeRequestPath(typeRequestInfo, name: TypeRequestPathName); } else { _currentTypeRequestPath.PushType(typeRequestInfo, true); } } var constructorCache = GetConstructorCache(autoCompleteDependencies); var constructorCacheKey = new ConstructorCacheKey(typeToConstruct, parameters); if (constructorCache.ContainsKey(constructorCacheKey)) { var cachedConstructor = constructorCache[constructorCacheKey]; var instanceCreatedWithInjection = TryCreateToConstruct(typeToConstruct, cachedConstructor, parameters, false, false); if (instanceCreatedWithInjection != null) { if (preventCircularDependencies) { CompleteTypeRequestPathIfRequired(typeRequestInfo); } return(instanceCreatedWithInjection); } Log.Warning("Found constructor for type '{0}' in constructor, but it failed to create an instance. Removing the constructor from the cache", typeToConstruct.FullName); constructorCache.Remove(constructorCacheKey); } Log.Debug("Creating instance of type '{0}' using specific parameters. No constructor found in the cache, so searching for the right one", typeToConstruct.FullName); var typeConstructorsMetadata = GetTypeMetaData(typeToConstruct); var constructors = typeConstructorsMetadata.GetConstructors(parameters.Count(), !autoCompleteDependencies); for (int i = 0; i < constructors.Count; i++) { var constructor = constructors[i]; var instanceCreatedWithInjection = TryCreateToConstruct(typeToConstruct, constructor, parameters, true, i < constructors.Count - 1); if (instanceCreatedWithInjection != null) { if (preventCircularDependencies) { CompleteTypeRequestPathIfRequired(typeRequestInfo); } // We found a constructor that works, cache it constructorCache[constructorCacheKey] = constructor; // Only update the rule when using a constructor for the first time, not when using it from the cache ApiCop.UpdateRule <TooManyDependenciesApiCopRule>("TypeFactory.LimitDependencyInjection", x => x.SetNumberOfDependenciesInjected(typeToConstruct, constructor.GetParameters().Count())); return(instanceCreatedWithInjection); } } Log.Debug("No constructor could be used, cannot construct type '{0}' with the specified parameters", typeToConstruct.FullName); } catch (CircularDependencyException) { throw; } catch (Exception ex) { if (preventCircularDependencies) { CloseCurrentTypeIfRequired(typeRequestInfo); } Log.Warning(ex, "Failed to construct type '{0}'", typeToConstruct.FullName); throw; } if (preventCircularDependencies) { CloseCurrentTypeIfRequired(typeRequestInfo); } return(null); } }
/// <summary> /// Creates an instance of the specified type using the specified parameters as injection values. /// </summary> /// <param name="typeToConstruct">The type to construct.</param> /// <param name="tag">The preferred tag when resolving dependencies.</param> /// <param name="parameters">The parameters to inject.</param> /// <param name="autoCompleteDependencies">if set to <c>true</c>, the additional dependencies will be auto completed.</param> /// <returns>The instantiated type using dependency injection.</returns> /// <exception cref="ArgumentNullException">The <paramref name="typeToConstruct" /> is <c>null</c>.</exception> private object CreateInstanceWithSpecifiedParameters(Type typeToConstruct, object tag, object[] parameters, bool autoCompleteDependencies) { Argument.IsNotNull("typeToConstruct", typeToConstruct); if (parameters == null) { parameters = ArrayShim.Empty <object>(); } var previousRequestPath = _currentTypeRequestPath.Value; try { var typeRequestInfo = new TypeRequestInfo(typeToConstruct); _currentTypeRequestPath.Value = TypeRequestPath.Branch(previousRequestPath, typeRequestInfo); var constructorCacheKey = new ConstructorCacheKey(typeToConstruct, autoCompleteDependencies, parameters); var typeConstructorsMetadata = GetTypeMetaData(typeToConstruct); var constructorCacheValue = GetConstructor(constructorCacheKey); if (constructorCacheValue.ConstructorInfo != null) { var cachedConstructor = constructorCacheValue.ConstructorInfo; var instanceCreatedWithInjection = TryCreateToConstruct(typeToConstruct, cachedConstructor, tag, parameters, false, false, typeConstructorsMetadata); if (instanceCreatedWithInjection != null) { return(instanceCreatedWithInjection); } Log.Warning("Found constructor for type '{0}' in constructor, but it failed to create an instance. Removing the constructor from the cache", typeToConstruct.FullName); SetConstructor(constructorCacheKey, constructorCacheValue, null); } Log.Debug("Creating instance of type '{0}' using specific parameters. No constructor found in the cache, so searching for the right one", typeToConstruct.FullName); var constructors = typeConstructorsMetadata.GetConstructors(parameters.Length, !autoCompleteDependencies).SortByParametersMatchDistance(parameters).ToList(); for (int i = 0; i < constructors.Count; i++) { var constructor = constructors[i]; var instanceCreatedWithInjection = TryCreateToConstruct(typeToConstruct, constructor, tag, parameters, true, i < constructors.Count - 1, typeConstructorsMetadata); if (instanceCreatedWithInjection != null) { // We found a constructor that works, cache it SetConstructor(constructorCacheKey, constructorCacheValue, constructor); // Only update the rule when using a constructor for the first time, not when using it from the cache ApiCop.UpdateRule <TooManyDependenciesApiCopRule>("TypeFactory.LimitDependencyInjection", x => x.SetNumberOfDependenciesInjected(typeToConstruct, constructor.GetParameters().Count())); return(instanceCreatedWithInjection); } } Log.Debug("No constructor could be used, cannot construct type '{0}' with the specified parameters", typeToConstruct.FullName); } catch (CircularDependencyException) { throw; } catch (Exception ex) { Log.Warning(ex, "Failed to construct type '{0}'", typeToConstruct.FullName); throw; } finally { _currentTypeRequestPath.Value = previousRequestPath; } return(null); }