54e1424b4749a95756f9eaf5a9f231476350c124
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / XamlBinding / DependencyService.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Reflection;
5 using Tizen.NUI.Binding.Internals;
6 using Tizen.NUI.Xaml;
7
8 namespace Tizen.NUI.Binding
9 {
10     internal static class DependencyService
11     {
12         static bool s_initialized;
13
14         static readonly List<Type> DependencyTypes = new List<Type>();
15         static readonly Dictionary<Type, DependencyData> DependencyImplementations = new Dictionary<Type, DependencyData>();
16
17         public static T Resolve<T>(DependencyFetchTarget fallbackFetchTarget = DependencyFetchTarget.GlobalInstance) where T : class
18         {
19             var result = DependencyResolver.Resolve(typeof(T)) as T;
20
21             return result ?? Get<T>(fallbackFetchTarget);
22         }
23
24         public static T Get<T>(DependencyFetchTarget fetchTarget = DependencyFetchTarget.GlobalInstance) where T : class
25         {
26             Initialize();
27
28             Type targetType = typeof(T);
29
30             if (!DependencyImplementations.ContainsKey(targetType))
31             {
32                 Type implementor = FindImplementor(targetType);
33                 DependencyImplementations[targetType] = implementor != null ? new DependencyData { ImplementorType = implementor } : null;
34             }
35
36             DependencyData dependencyImplementation = DependencyImplementations[targetType];
37             if (dependencyImplementation == null)
38                 return null;
39
40             if (fetchTarget == DependencyFetchTarget.GlobalInstance)
41             {
42                 if (dependencyImplementation.GlobalInstance == null)
43                 {
44                     dependencyImplementation.GlobalInstance = Activator.CreateInstance(dependencyImplementation.ImplementorType);
45                 }
46                 return (T)dependencyImplementation.GlobalInstance;
47             }
48             return (T)Activator.CreateInstance(dependencyImplementation.ImplementorType);
49         }
50
51         public static void Register<T>() where T : class
52         {
53             Type type = typeof(T);
54             if (!DependencyTypes.Contains(type))
55                 DependencyTypes.Add(type);
56         }
57
58         public static void Register<T, TImpl>() where T : class where TImpl : class, T
59         {
60             Type targetType = typeof(T);
61             Type implementorType = typeof(TImpl);
62             if (!DependencyTypes.Contains(targetType))
63                 DependencyTypes.Add(targetType);
64
65             DependencyImplementations[targetType] = new DependencyData { ImplementorType = implementorType };
66         }
67
68         static Type FindImplementor(Type target)
69         {
70             return DependencyTypes.FirstOrDefault(t => target.IsAssignableFrom(t));
71         }
72
73         static void Initialize()
74         {
75             if (s_initialized)
76             {
77                 return;
78             }
79
80             Assembly[] assemblies = Device.GetAssemblies();
81             if (Tizen.NUI.Binding.Internals.Registrar.ExtraAssemblies != null)
82             {
83                 assemblies = assemblies.Union(Tizen.NUI.Binding.Internals.Registrar.ExtraAssemblies).ToArray();
84             }
85
86             Initialize(assemblies);
87         }
88
89         internal static void Initialize(Assembly[] assemblies)
90         {
91             if (s_initialized || assemblies == null)
92             {
93                 return;
94             }
95             DependencyService.Register<IValueConverterProvider, ValueConverterProvider>();
96
97             Type targetAttrType = typeof(DependencyAttribute);
98
99             // Don't use LINQ for performance reasons
100             // Naive implementation can easily take over a second to run
101             foreach (Assembly assembly in assemblies)
102             {
103                 Attribute[] attributes;
104                 try
105                 {
106                     attributes = assembly.GetCustomAttributes(targetAttrType).ToArray();
107                 }
108                 catch (System.IO.FileNotFoundException)
109                 {
110                     // Sometimes the previewer doesn't actually have everything required for these loads to work
111                     Console.WriteLine(nameof(Registrar), "Could not load assembly: {0} for Attibute {1} | Some renderers may not be loaded", assembly.FullName, targetAttrType.FullName);
112                     continue;
113                 }
114                 
115                 if (attributes.Length == 0)
116                     continue;
117
118                 foreach (DependencyAttribute attribute in attributes)
119                 {
120                     if (!DependencyTypes.Contains(attribute.Implementor))
121                     {
122                         DependencyTypes.Add(attribute.Implementor);
123                     }
124                 }
125             }
126
127             s_initialized = true;
128         }
129
130         class DependencyData
131         {
132             public object GlobalInstance { get; set; }
133
134             public Type ImplementorType { get; set; }
135         }
136     }
137 }