codecd

这篇博客深入探讨了Xamarin.Forms中的路由注册与管理,包括RouteFactory和Routing静态类的功能,以及如何创建和查找页面内容。同时,文章也介绍了DependencyService,它是Xamarin.Forms中实现依赖注入的机制,用于跨平台获取服务实例。内容涵盖了注册、解析和初始化过程。
摘要由CSDN通过智能技术生成
using System;

namespace Xamarin.Forms
{
	public abstract class RouteFactory
	{
		public abstract Element GetOrCreate();
	}
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Xamarin.Forms
{
	public static class Routing
	{
		static int s_routeCount = 0;
		static Dictionary<string, RouteFactory> s_routes = new Dictionary<string, RouteFactory>();
		static Dictionary<string, Page> s_implicitPageRoutes = new Dictionary<string, Page>();

		const string ImplicitPrefix = "IMPL_";
		const string DefaultPrefix = "D_FAULT_";
		internal const string PathSeparator = "/";

		// We only need these while a navigation is happening 
		internal static void ClearImplicitPageRoutes()
		{
			s_implicitPageRoutes.Clear();
		}

		internal static void RegisterImplicitPageRoute(Page page)
		{
			var route = GetRoute(page);
			if (!IsUserDefined(route))
				s_implicitPageRoutes[route] = page;
		}

		// Shell works much better if the entire nav stack can be represented by a string
		// If the users pushes pages without using routes we want these page keys tracked
		internal static void RegisterImplicitPageRoutes(Shell shell)
		{
			foreach (var item in shell.Items)
			{
				foreach (var section in item.Items)
				{
					var navigationStackCount = section.Navigation.NavigationStack.Count;
					for (int i = 1; i < navigationStackCount; i++)
					{
						RegisterImplicitPageRoute(section.Navigation.NavigationStack[i]);
					}
					var navigationModalStackCount = section.Navigation.ModalStack.Count;
					for (int i = 0; i < navigationModalStackCount; i++)
					{
						var page = section.Navigation.ModalStack[i];
						RegisterImplicitPageRoute(page);

						if (page is NavigationPage np)
						{
							foreach (var npPages in np.Pages)
							{
								RegisterImplicitPageRoute(npPages);
							}
						}
					}
				}
			}
		}

		internal static string GenerateImplicitRoute(string source)
		{
			if (IsImplicit(source))
				return source;

			return String.Concat(ImplicitPrefix, source);
		}

		internal static bool IsImplicit(string source)
		{
			return source.StartsWith(ImplicitPrefix, StringComparison.Ordinal);
		}

		internal static bool IsImplicit(BindableObject source)
		{
			return IsImplicit(GetRoute(source));
		}

		internal static bool IsDefault(string source)
		{
			return source.StartsWith(DefaultPrefix, StringComparison.Ordinal);
		}

		internal static bool IsDefault(BindableObject source)
		{
			return IsDefault(GetRoute(source));
		}

		internal static bool IsUserDefined(BindableObject source)
		{
			if (source == null)
				return false;

			return IsUserDefined(GetRoute(source));
		}

		internal static bool IsUserDefined(string route)
		{
			if (route == null)
				return false;

			return !(IsDefault(route) || IsImplicit(route));
		}

		internal static void Clear()
		{
			s_implicitPageRoutes.Clear();
			s_routes.Clear();
		}

		public static readonly BindableProperty RouteProperty =
			BindableProperty.CreateAttached("Route", typeof(string), typeof(Routing), null,
				defaultValueCreator: CreateDefaultRoute);

		static object CreateDefaultRoute(BindableObject bindable)
		{
			return $"{DefaultPrefix}{bindable.GetType().Name}{++s_routeCount}";
		}

		internal static string[] GetRouteKeys()
		{
			string[] keys = new string[s_routes.Count + s_implicitPageRoutes.Count];
			s_routes.Keys.CopyTo(keys, 0);
			s_implicitPageRoutes.Keys.CopyTo(keys, s_routes.Count);
			return keys;
		}

		public static Element GetOrCreateContent(string route)
		{
			Element result = null;

			if (s_implicitPageRoutes.TryGetValue(route, out var page))
			{
				return page;
			}

			if (s_routes.TryGetValue(route, out var content))
				result = content.GetOrCreate();

			if (result == null)
			{
				// okay maybe its a type, we'll try that just to be nice to the user
				var type = Type.GetType(route);
				if (type != null)
					result = Activator.CreateInstance(type) as Element;
			}

			if (result != null)
				SetRoute(result, route);

			return result;
		}

		public static string GetRoute(BindableObject obj)
		{
			return (string)obj.GetValue(RouteProperty);
		}

		internal static string GetRoutePathIfNotImplicit(Element obj)
		{
			var source = GetRoute(obj);
			if (IsImplicit(source))
				return String.Empty;

			return $"{source}/";
		}

		public static string FormatRoute(List<string> segments)
		{
			var route = FormatRoute(String.Join(PathSeparator, segments));
			return route;
		}

		public static string FormatRoute(string route)
		{
			return route;
		}

		public static void RegisterRoute(string route, RouteFactory factory)
		{
			if (!String.IsNullOrWhiteSpace(route))
				route = FormatRoute(route);
			ValidateRoute(route, factory);

			s_routes[route] = factory;
		}

		public static void UnRegisterRoute(string route)
		{
			if (s_routes.TryGetValue(route, out _))
				s_routes.Remove(route);
		}

		public static void RegisterRoute(string route, Type type)
		{
			RegisterRoute(route, new TypeRouteFactory(type));
		}

		public static void SetRoute(Element obj, string value)
		{
			obj.SetValue(RouteProperty, value);
		}

		static void ValidateRoute(string route, RouteFactory routeFactory)
		{
			if (string.IsNullOrWhiteSpace(route))
				throw new ArgumentNullException(nameof(route), "Route cannot be an empty string");

			routeFactory = routeFactory ?? throw new ArgumentNullException(nameof(routeFactory), "Route Factory cannot be null");

			var uri = new Uri(route, UriKind.RelativeOrAbsolute);

			var parts = uri.OriginalString.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (var part in parts)
			{
				if (IsImplicit(part))
					throw new ArgumentException($"Route contains invalid characters in \"{part}\"");
			}

			RouteFactory existingRegistration = null;
			if (s_routes.TryGetValue(route, out existingRegistration) && !existingRegistration.Equals(routeFactory))
				throw new ArgumentException($"Duplicated Route: \"{route}\"");
		}

		class TypeRouteFactory : RouteFactory
		{
			readonly Type _type;

			public TypeRouteFactory(Type type)
			{
				_type = type;
			}

			public override Element GetOrCreate()
			{
				return (Element)Activator.CreateInstance(_type);
			}
			public override bool Equals(object obj)
			{
				if ((obj is TypeRouteFactory typeRouteFactory))
					return typeRouteFactory._type == _type;

				return false;
			}

			public override int GetHashCode()
			{
				return _type.GetHashCode();
			}
		}
	}
}





using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Xamarin.Forms.Internals;

namespace Xamarin.Forms
{
	public static class DependencyService
	{
		static bool s_initialized;

		static readonly object s_dependencyLock = new object();
		static readonly object s_initializeLock = new object();

		static readonly List<Type> DependencyTypes = new List<Type>();
		static readonly Dictionary<Type, DependencyData> DependencyImplementations = new Dictionary<Type, DependencyData>();

		public static T Resolve<T>(DependencyFetchTarget fallbackFetchTarget = DependencyFetchTarget.GlobalInstance) where T : class
		{
			var result = DependencyResolver.Resolve(typeof(T)) as T;

			return result ?? Get<T>(fallbackFetchTarget);
		}

		public static T Get<T>(DependencyFetchTarget fetchTarget = DependencyFetchTarget.GlobalInstance) where T : class
		{
			Initialize();

			DependencyData dependencyImplementation;
			lock (s_dependencyLock)
			{
				Type targetType = typeof(T);
				if (!DependencyImplementations.TryGetValue(targetType, out dependencyImplementation))
				{
					Type implementor = FindImplementor(targetType);
					DependencyImplementations[targetType] = (dependencyImplementation = implementor != null ? new DependencyData { ImplementorType = implementor } : null);
				}
			}

			if (dependencyImplementation == null)
				return null;

			if (fetchTarget == DependencyFetchTarget.GlobalInstance)
			{
				if (dependencyImplementation.GlobalInstance == null)
				{
					lock (dependencyImplementation)
					{
						if (dependencyImplementation.GlobalInstance == null)
						{
							dependencyImplementation.GlobalInstance = Activator.CreateInstance(dependencyImplementation.ImplementorType);
						}
					}
				}
				return (T)dependencyImplementation.GlobalInstance;
			}
			return (T)Activator.CreateInstance(dependencyImplementation.ImplementorType);
		}

		public static void Register<T>() where T : class
		{
			Type type = typeof(T);
			if (!DependencyTypes.Contains(type))
				DependencyTypes.Add(type);
		}

		public static void Register<T, TImpl>() where T : class where TImpl : class, T
		{
			Type targetType = typeof(T);
			Type implementorType = typeof(TImpl);
			if (!DependencyTypes.Contains(targetType))
				DependencyTypes.Add(targetType);

			lock (s_dependencyLock)
				DependencyImplementations[targetType] = new DependencyData { ImplementorType = implementorType };
		}

		public static void RegisterSingleton<T>(T instance) where T : class
		{
			Type targetType = typeof(T);
			Type implementorType = typeof(T);
			if (!DependencyTypes.Contains(targetType))
				DependencyTypes.Add(targetType);

			lock (s_dependencyLock)
				DependencyImplementations[targetType] = new DependencyData { ImplementorType = implementorType, GlobalInstance = instance };
		}

		static Type FindImplementor(Type target) =>
			DependencyTypes.FirstOrDefault(t => target.IsAssignableFrom(t));

		static void Initialize()
		{
			if (s_initialized)
				return;

			lock (s_initializeLock)
			{
				if (s_initialized)
					return;

				Assembly[] assemblies = Device.GetAssemblies();
				if (Internals.Registrar.ExtraAssemblies != null)
				{
					assemblies = assemblies.Union(Internals.Registrar.ExtraAssemblies).ToArray();
				}

				Initialize(assemblies);
			}
		}

		internal static void Initialize(Assembly[] assemblies)
		{
			if (s_initialized)
				return;

			lock (s_initializeLock)
			{
				if (s_initialized)
					return;

				// Don't use LINQ for performance reasons
				// Naive implementation can easily take over a second to run
				foreach (Assembly assembly in assemblies)
				{
					object[] attributes = assembly.GetCustomAttributesSafe(typeof(DependencyAttribute));
					if (attributes == null)
						continue;

					for (int i = 0; i < attributes.Length; i++)
					{
						DependencyAttribute attribute = (DependencyAttribute)attributes[i];
						if (!DependencyTypes.Contains(attribute.Implementor))
						{
							DependencyTypes.Add(attribute.Implementor);
						}
					}
				}

				s_initialized = true;
			}
		}

		class DependencyData
		{
			public object GlobalInstance { get; set; }

			public Type ImplementorType { get; set; }
		}
	}
}




using System;

namespace Xamarin.Forms
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	public sealed class DependencyAttribute : Attribute
	{
		public DependencyAttribute(Type implementorType)
		{
			Implementor = implementorType;
		}

		internal Type Implementor { get; private set; }
	}
}


	public Assembly[] GetAssemblies()
		{
			return AppDomain.CurrentDomain.GetAssemblies();
		}



   public Uri Location
        {
            get;
            private set;
        }
		
		
		

internal class RequestDefinition
	{
		public RequestDefinition(RouteRequestBuilder theWinningRoute, Shell shell)
		{
			Item = theWinningRoute.Item;
			Section = theWinningRoute.Section ?? Item?.CurrentItem;
			Content = theWinningRoute.Content ?? Section?.CurrentItem;
			GlobalRoutes = theWinningRoute.GlobalRouteMatches;

			List<String> builder = new List<string>();
			if (Item?.Route != null)
				builder.Add(Item.Route);

			if (Section?.Route != null)
				builder.Add(Section?.Route);

			if (Content?.Route != null)
				builder.Add(Content?.Route);

			if (GlobalRoutes != null)
				builder.AddRange(GlobalRoutes);

			var uriPath = MakeUriString(builder);
			var uri = ShellUriHandler.CreateUri(uriPath);
			FullUri = ShellUriHandler.ConvertToStandardFormat(shell, uri);

		}

		string MakeUriString(List<string> segments)
		{
			if (segments[0].StartsWith("/", StringComparison.Ordinal) || segments[0].StartsWith("\\", StringComparison.Ordinal))
				return String.Join("/", segments);

			return $"//{String.Join("/", segments)}";
		}

		public Uri FullUri { get; }
		public ShellItem Item { get; }
		public ShellSection Section { get; }
		public ShellContent Content { get; }
		public List<string> GlobalRoutes { get; }
	}




IDictionary<string, string> MergeData(Element shellElement, IDictionary<string, string> data, bool isPopping)
			{
				if (!isPopping)
					return data;

				var returnValue = new Dictionary<string, string>(data);

				var existing = (IDictionary<string, string>)shellElement.GetValue(ShellContent.QueryAttributesProperty);

				if (existing == null)
					return data;

				foreach (var datum in existing)
				{
					if (!returnValue.ContainsKey(datum.Key))
						returnValue[datum.Key] = datum.Value;
				}

				return returnValue;
			}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Farmwang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值