eaab18386de171ddfbe824d787120c6bc4cc2667
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / XamlBinding / Registrar.cs
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Linq;
5 using System.Reflection;
6 using Tizen.NUI.Binding;
7
8 namespace Tizen.NUI.Binding
9 {
10         // Previewer uses reflection to bind to this method; Removal or modification of visibility will break previewer.
11         internal static class Registrar
12         {
13                 internal static void RegisterAll(Type[] attrTypes) => Internals.Registrar.RegisterAll(attrTypes);
14         }
15 }
16
17 namespace Tizen.NUI.Internals
18 {
19     /// <summary>
20     /// For internal use.
21     /// </summary>
22     /// <typeparam name="TRegistrable"></typeparam>
23         [EditorBrowsable(EditorBrowsableState.Never)]
24         public class Registrar<TRegistrable> where TRegistrable : class
25         {
26                 readonly Dictionary<Type, Type> _handlers = new Dictionary<Type, Type>();
27
28         /// <summary>
29         /// Register.
30         /// </summary>
31         /// <param name="tview">The type of the view</param>
32         /// <param name="trender">The type of the render.</param>
33                 public void Register(Type tview, Type trender)
34                 {
35                         //avoid caching null renderers
36                         if (trender == null)
37                                 return;
38                         _handlers[tview] = trender;
39                 }
40
41                 internal TRegistrable GetHandler(Type type)
42                 {
43                         Type handlerType = GetHandlerType(type);
44                         if (handlerType == null)
45                                 return null;
46
47                         object handler = DependencyResolver.ResolveOrCreate(handlerType);
48
49                         return (TRegistrable)handler;
50                 }
51
52                 internal TRegistrable GetHandler(Type type, params object[] args)
53                 {
54                         if (args.Length == 0)
55                         {
56                                 return GetHandler(type);
57                         }
58
59                         Type handlerType = GetHandlerType(type);
60                         if (handlerType == null)
61                                 return null;
62
63                         return (TRegistrable)DependencyResolver.ResolveOrCreate(handlerType, args);
64                 }
65
66         /// <summary>
67         /// For internal use. Returns handler.
68         /// </summary>
69         /// <typeparam name="TOut">The type of the handler</typeparam>
70         /// <param name="type">The type.</param>
71         /// <returns>The handler instance.</returns>
72                 public TOut GetHandler<TOut>(Type type) where TOut : TRegistrable
73                 {
74                         return (TOut)GetHandler(type);
75                 }
76
77         /// <summary>
78         /// For internal use. Returns handler.
79         /// </summary>
80         /// <typeparam name="TOut">The type of the handler</typeparam>
81         /// <param name="type">The type.</param>
82         /// <param name="args">The args of the type</param>
83         /// <returns>The handler instance.</returns>
84                 public TOut GetHandler<TOut>(Type type, params object[] args) where TOut : TRegistrable
85                 {
86                         return (TOut)GetHandler(type, args);
87                 }
88
89         /// <summary>
90         /// For internal use. Return the handler of the object.
91         /// </summary>
92         /// <typeparam name="TOut">Thetype</typeparam>
93         /// <param name="obj">The object instance.</param>
94         /// <returns>The handle of the obj.</returns>
95                 public TOut GetHandlerForObject<TOut>(object obj) where TOut : TRegistrable
96                 {
97                         if (obj == null)
98                                 throw new ArgumentNullException(nameof(obj));
99
100                         var reflectableType = obj as IReflectableType;
101                         var type = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : obj.GetType();
102
103                         return (TOut)GetHandler(type);
104                 }
105
106         /// <summary>
107         /// For inetrnal use. Return the handler of the object.
108         /// </summary>
109         /// <typeparam name="TOut">The type</typeparam>
110         /// <param name="obj">The object instance</param>
111         /// <param name="args">The args of the type</param>
112         /// <returns>The handler of the object.</returns>
113                 public TOut GetHandlerForObject<TOut>(object obj, params object[] args) where TOut : TRegistrable
114                 {
115                         if (obj == null)
116                                 throw new ArgumentNullException(nameof(obj));
117
118                         var reflectableType = obj as IReflectableType;
119                         var type = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : obj.GetType();
120
121                         return (TOut)GetHandler(type, args);
122                 }
123
124         /// <summary>
125         /// For internal use. Returns the handle type.
126         /// </summary>
127         /// <param name="viewType">The view type.</param>
128         /// <returns>The type of the handle.</returns>
129                 public Type GetHandlerType(Type viewType)
130                 {
131                         Type type;
132                         if (LookupHandlerType(viewType, out type))
133                                 return type;
134
135                         // lazy load render-view association with RenderWithAttribute (as opposed to using ExportRenderer)
136                         var attribute = viewType.GetTypeInfo().GetCustomAttribute<RenderWithAttribute>();
137                         if (attribute == null)
138                         {
139                                 Register(viewType, null); // Cache this result so we don't have to do GetCustomAttribute again
140                                 return null;
141                         }
142
143                         type = attribute.Type;
144
145                         if (type.Name.StartsWith("_", StringComparison.Ordinal))
146                         {
147                                 // TODO: Remove attribute2 once renderer names have been unified across all platforms
148                                 var attribute2 = type.GetTypeInfo().GetCustomAttribute<RenderWithAttribute>();
149                                 if (attribute2 != null)
150                                         type = attribute2.Type;
151
152                                 if (type.Name.StartsWith("_", StringComparison.Ordinal))
153                                 {
154                                         Register(viewType, null); // Cache this result so we don't work through this chain again
155                                         return null;
156                                 }
157                         }
158
159                         Register(viewType, type); // Register this so we don't have to look for the RenderWith Attibute again in the future
160
161                         return type;
162                 }
163
164         /// <summary>
165         /// For internal use. Return the handle type of the object
166         /// </summary>
167         /// <param name="obj">The object instance.</param>
168         /// <returns>The type of the handler.</returns>
169                 public Type GetHandlerTypeForObject(object obj)
170                 {
171                         if (obj == null)
172                                 throw new ArgumentNullException(nameof(obj));
173
174                         var reflectableType = obj as IReflectableType;
175                         var type = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : obj.GetType();
176
177                         return GetHandlerType(type);
178                 }
179
180                 bool LookupHandlerType(Type viewType, out Type handlerType)
181                 {
182                         Type type = viewType;
183
184                         while (type != null)
185                         {
186                                 if (_handlers.ContainsKey(type))
187                                 {
188                                         handlerType = _handlers[type];
189                                         return true;
190                                 }
191
192                                 type = type.GetTypeInfo().BaseType;
193                         }
194
195                         handlerType = null;
196                         return false;
197                 }
198         }
199
200     /// <summary>
201     /// For internal use
202     /// </summary>
203         [EditorBrowsable(EditorBrowsableState.Never)]
204         internal static class Registrar
205         {
206                 static Registrar()
207                 {
208                         Registered = new Registrar<IRegisterable>();
209                 }
210
211                 internal static Dictionary<string, Type> Effects { get; } = new Dictionary<string, Type>();
212                 internal static Dictionary<string, StyleSheets.StylePropertyAttribute> StyleProperties { get; } = new Dictionary<string, StyleSheets.StylePropertyAttribute>();
213
214                 public static IEnumerable<Assembly> ExtraAssemblies { get; set; }
215
216                 public static Registrar<IRegisterable> Registered { get; internal set; }
217
218                 public static void RegisterAll(Type[] attrTypes)
219                 {
220                         Assembly[] assemblies = Device.GetAssemblies();
221                         if (ExtraAssemblies != null)
222                                 assemblies = assemblies.Union(ExtraAssemblies).ToArray();
223
224                         Assembly defaultRendererAssembly = Device.PlatformServices.GetType().GetTypeInfo().Assembly;
225                         int indexOfExecuting = Array.IndexOf(assemblies, defaultRendererAssembly);
226
227                         if (indexOfExecuting > 0)
228                         {
229                                 assemblies[indexOfExecuting] = assemblies[0];
230                                 assemblies[0] = defaultRendererAssembly;
231                         }
232
233                         // Don't use LINQ for performance reasons
234                         // Naive implementation can easily take over a second to run
235                         foreach (Assembly assembly in assemblies)
236                         {
237                                 foreach (Type attrType in attrTypes)
238                                 {
239                                         Attribute[] attributes;
240                                         try
241                                         {
242                                                 attributes = assembly.GetCustomAttributes(attrType).ToArray();
243                                         }
244                                         catch (System.IO.FileNotFoundException)
245                                         {
246                                                 // Sometimes the previewer doesn't actually have everything required for these loads to work
247                                                 Console.WriteLine(nameof(Registrar), "Could not load assembly: {0} for Attibute {1} | Some renderers may not be loaded", assembly.FullName, attrType.FullName);
248                                                 continue;
249                                         }
250                                         var length = attributes.Length;
251                                         for (var i = 0; i < length;i++)
252                                         {
253                                                 var attribute = (HandlerAttribute)attributes[i];
254                                                 if (attribute.ShouldRegister())
255                                                         Registered.Register(attribute.HandlerType, attribute.TargetType);
256                                         }
257                                 }
258
259                                 string resolutionName = assembly.FullName;
260                                 var resolutionNameAttribute = (ResolutionGroupNameAttribute)assembly.GetCustomAttribute(typeof(ResolutionGroupNameAttribute));
261                                 if (resolutionNameAttribute != null)
262                                         resolutionName = resolutionNameAttribute.ShortName;
263
264                                 Attribute[] effectAttributes = assembly.GetCustomAttributes(typeof(ExportEffectAttribute)).ToArray();
265                                 var exportEffectsLength = effectAttributes.Length;
266                                 for (var i = 0; i < exportEffectsLength;i++)
267                                 {
268                                         var effect = (ExportEffectAttribute)effectAttributes[i];
269                                         Effects [resolutionName + "." + effect.Id] = effect.Type;
270                                 }
271
272                                 Attribute[] styleAttributes = assembly.GetCustomAttributes(typeof(StyleSheets.StylePropertyAttribute)).ToArray();
273                                 var stylePropertiesLength = styleAttributes.Length;
274                                 for (var i = 0; i < stylePropertiesLength; i++)
275                                 {
276                                         var attribute = (StyleSheets.StylePropertyAttribute)styleAttributes[i];
277                                         StyleProperties[attribute.CssPropertyName] = attribute;
278                                 }
279                         }
280
281                         DependencyService.Initialize(assemblies);
282                 }
283         }
284 }