private static void BeginLoad_OnUIThread(AsyncCallback userCallback, PageResourceContentLoaderAsyncResult result) { if (result.Exception != null) { result.IsCompleted = true; userCallback(result); return; } try { string pagePathAndName = UriParsingHelper.InternalUriGetBaseValue(result.Uri); string xaml = GetLocalXaml(pagePathAndName); if (String.IsNullOrEmpty(xaml)) { result.Exception = new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, Resource.PageResourceContentLoader_NoXAMLWasFound, pagePathAndName)); return; } string classString = GetXClass(xaml); if (String.IsNullOrEmpty(classString)) { try { result.Content = XamlReader.Load(xaml); } catch (Exception ex) { result.Exception = new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, Resource.PageResourceContentLoader_XAMLWasUnloadable, pagePathAndName), ex); return; } } else { // If it does have an x:Class attribute, then it has a // code-behind, so get the CLR type of the XAML instead. Type t = GetTypeFromAnyLoadedAssembly(classString); if (t == null) { result.Exception = new InvalidOperationException(String.Format( CultureInfo.CurrentCulture, Resource.PageResourceContentLoader_TheTypeSpecifiedInTheXClassCouldNotBeFound, classString, pagePathAndName)); return; } result.Content = Activator.CreateInstance(t); return; } } catch (Exception ex) { result.Exception = ex; } finally { result.IsCompleted = true; if (userCallback != null) { userCallback(result); } } }
/// <summary> /// Attempts to process a Uri, if it matches the Uri template /// </summary> /// <param name="uri">The Uri to map</param> /// <returns>The Uri after mapping, or null if mapping did not succeed</returns> public Uri MapUri(Uri uri) { this.CheckPreconditions(); if (this._uriRegex == null) { // If an empty Uri was passed in, we can map that even with an empty Uri Template. if (uri == null || uri.OriginalString == null || uri.OriginalString.Length == 0) { return new Uri(this._mappedUri.OriginalString, UriKind.Relative); } // Otherwise, this does not match anything else { return null; } } string originalUriWithoutQueryString = UriParsingHelper.InternalUriGetBaseValue(uri); Match m = this._uriRegex.Match(originalUriWithoutQueryString); if (!m.Success) { return null; } string uriAfterMappingBase = UriParsingHelper.InternalUriGetBaseValue(this._mappedUri); IDictionary<string, string> uriAfterMappingQueryString = UriParsingHelper.InternalUriParseQueryStringToDictionary(this._mappedUri, false /* decodeResults */); IDictionary<string, string> originalQueryString = UriParsingHelper.InternalUriParseQueryStringToDictionary(uri, false /* decodeResults */); string originalFragment = UriParsingHelper.InternalUriGetFragment(uri); string uriAfterMappingFragment = UriParsingHelper.InternalUriGetFragment(this._mappedUri); // 'uriValues' is the values of the identifiers from the 'Uri' template, as they appear in the Uri // being processed IDictionary<string, string> uriValues = new Dictionary<string, string>(); // i begins at 1 because the group at index 0 is always equal to the parent's Match, // which we do not want. We only want explicitly-named groups. int groupCount = m.Groups.Count; for (int i = 1; i < groupCount; i++) { uriValues.Add(this._uriRegex.GroupNameFromNumber(i), m.Groups[i].Value); } foreach (string identifier in this._mappedUriIdentifiers) { string identifierWithBraces = "{" + identifier + "}"; string replacementValue = (uriValues.ContainsKey(identifier) ? uriValues[identifier] : String.Empty); // First check for identifiers in the base Uri, and replace them as appropriate uriAfterMappingBase = uriAfterMappingBase.Replace(identifierWithBraces, replacementValue); // Then, look through the query string (both the key and the value) and replace as appropriate string[] keys = new string[uriAfterMappingQueryString.Keys.Count]; uriAfterMappingQueryString.Keys.CopyTo(keys, 0); foreach (string key in keys) { // First check if the value contains it, as this is an easy replacement if (uriAfterMappingQueryString[key].Contains(identifierWithBraces)) { if (uriValues.ContainsKey(identifier)) { uriAfterMappingQueryString[key] = uriAfterMappingQueryString[key].Replace(identifierWithBraces, replacementValue); } } // If the key itself contains the identifier, then we need to remove the existing item with the key that // contains the identifier, and re-add to the dictionary with the new key and the pre-existing value if (key.Contains(identifierWithBraces)) { string existingVal = uriAfterMappingQueryString[key]; uriAfterMappingQueryString.Remove(key); uriAfterMappingQueryString.Add(key.Replace(identifierWithBraces, replacementValue), existingVal); } } // If there's an original fragment already present, it will always win, so don't bother doing replacements if (String.IsNullOrEmpty(originalFragment) && !String.IsNullOrEmpty(uriAfterMappingFragment)) { if (uriAfterMappingFragment.Contains(identifierWithBraces)) { uriAfterMappingFragment = uriAfterMappingFragment.Replace(identifierWithBraces, replacementValue); } } } foreach (string key in originalQueryString.Keys) { if (!uriAfterMappingQueryString.ContainsKey(key)) { uriAfterMappingQueryString.Add(key, originalQueryString[key]); } else { // If a value is present in the originally-navigated-to query string, it // takes precedence over anything in the aliased query string by default. uriAfterMappingQueryString[key] = originalQueryString[key]; } } if (!String.IsNullOrEmpty(originalFragment)) { uriAfterMappingFragment = originalFragment; } return UriParsingHelper.InternalUriCreateWithQueryStringValues(uriAfterMappingBase, uriAfterMappingQueryString, uriAfterMappingFragment); }