116 строки
3.0 KiB
C#
116 строки
3.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
namespace Xamarin.Forms
|
|
{
|
|
public static class DependencyService
|
|
{
|
|
static bool s_initialized;
|
|
|
|
static readonly List<Type> DependencyTypes = new List<Type>();
|
|
static readonly Dictionary<Type, DependencyData> DependencyImplementations = new Dictionary<Type, DependencyData>();
|
|
|
|
public static T Get<T>(DependencyFetchTarget fetchTarget = DependencyFetchTarget.GlobalInstance) where T : class
|
|
{
|
|
Initialize();
|
|
|
|
Type targetType = typeof(T);
|
|
|
|
if (!DependencyImplementations.ContainsKey(targetType))
|
|
{
|
|
Type implementor = FindImplementor(targetType);
|
|
DependencyImplementations[targetType] = implementor != null ? new DependencyData { ImplementorType = implementor } : null;
|
|
}
|
|
|
|
DependencyData dependencyImplementation = DependencyImplementations[targetType];
|
|
if (dependencyImplementation == null)
|
|
return null;
|
|
|
|
if (fetchTarget == DependencyFetchTarget.GlobalInstance)
|
|
{
|
|
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);
|
|
|
|
DependencyImplementations[targetType] = new DependencyData { ImplementorType = implementorType };
|
|
}
|
|
|
|
static Type FindImplementor(Type target)
|
|
{
|
|
return DependencyTypes.FirstOrDefault(t => target.IsAssignableFrom(t));
|
|
}
|
|
|
|
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
|
|
// Naive implementation can easily take over a second to run
|
|
foreach (Assembly assembly in assemblies)
|
|
{
|
|
Attribute[] attributes = assembly.GetCustomAttributes(targetAttrType).ToArray();
|
|
if (attributes.Length == 0)
|
|
continue;
|
|
|
|
foreach (DependencyAttribute attribute in attributes)
|
|
{
|
|
if (!DependencyTypes.Contains(attribute.Implementor))
|
|
{
|
|
DependencyTypes.Add(attribute.Implementor);
|
|
}
|
|
}
|
|
}
|
|
|
|
s_initialized = true;
|
|
}
|
|
|
|
class DependencyData
|
|
{
|
|
public object GlobalInstance { get; set; }
|
|
|
|
public Type ImplementorType { get; set; }
|
|
}
|
|
}
|
|
} |