[NUI] Adjust directory (#903)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / 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.Internals
9 {
10     /// <summary>
11     /// For internal use.
12     /// </summary>
13     /// <typeparam name="TRegistrable"></typeparam>
14     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
15     [EditorBrowsable(EditorBrowsableState.Never)]
16     public class Registrar<TRegistrable> where TRegistrable : class
17     {
18         readonly Dictionary<Type, Type> _handlers = new Dictionary<Type, Type>();
19
20         /// <summary>
21         /// Register.
22         /// </summary>
23         /// <param name="tview">The type of the view</param>
24         /// <param name="trender">The type of the render.</param>
25         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
26         [EditorBrowsable(EditorBrowsableState.Never)]
27         public void Register(Type tview, Type trender)
28         {
29             //avoid caching null renderers
30             if (trender == null)
31                 return;
32             _handlers[tview] = trender;
33         }
34
35         internal TRegistrable GetHandler(Type type)
36         {
37             Type handlerType = GetHandlerType(type);
38             if (handlerType == null)
39                 return null;
40
41             object handler = DependencyResolver.ResolveOrCreate(handlerType);
42
43             return (TRegistrable)handler;
44         }
45
46         internal TRegistrable GetHandler(Type type, params object[] args)
47         {
48             if (args.Length == 0)
49             {
50                 return GetHandler(type);
51             }
52
53             Type handlerType = GetHandlerType(type);
54             if (handlerType == null)
55                 return null;
56
57             return (TRegistrable)DependencyResolver.ResolveOrCreate(handlerType, args);
58         }
59
60         /// <summary>
61         /// For internal use. Returns handler.
62         /// </summary>
63         /// <typeparam name="TOut">The type of the handler</typeparam>
64         /// <param name="type">The type.</param>
65         /// <returns>The handler instance.</returns>
66         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
67         [EditorBrowsable(EditorBrowsableState.Never)]
68         public TOut GetHandler<TOut>(Type type) where TOut : TRegistrable
69         {
70             return (TOut)GetHandler(type);
71         }
72
73         /// <summary>
74         /// For internal use. Returns handler.
75         /// </summary>
76         /// <typeparam name="TOut">The type of the handler</typeparam>
77         /// <param name="type">The type.</param>
78         /// <param name="args">The args of the type</param>
79         /// <returns>The handler instance.</returns>
80         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
81         [EditorBrowsable(EditorBrowsableState.Never)]
82         public TOut GetHandler<TOut>(Type type, params object[] args) where TOut : TRegistrable
83         {
84             return (TOut)GetHandler(type, args);
85         }
86
87         /// <summary>
88         /// For internal use. Return the handler of the object.
89         /// </summary>
90         /// <typeparam name="TOut">Thetype</typeparam>
91         /// <param name="obj">The object instance.</param>
92         /// <returns>The handle of the obj.</returns>
93         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
94         [EditorBrowsable(EditorBrowsableState.Never)]
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         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
114         [EditorBrowsable(EditorBrowsableState.Never)]
115         public TOut GetHandlerForObject<TOut>(object obj, params object[] args) where TOut : TRegistrable
116         {
117             if (obj == null)
118                 throw new ArgumentNullException(nameof(obj));
119
120             var reflectableType = obj as IReflectableType;
121             var type = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : obj.GetType();
122
123             return (TOut)GetHandler(type, args);
124         }
125
126         /// <summary>
127         /// For internal use. Returns the handle type.
128         /// </summary>
129         /// <param name="viewType">The view type.</param>
130         /// <returns>The type of the handle.</returns>
131         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
132         [EditorBrowsable(EditorBrowsableState.Never)]
133         public Type GetHandlerType(Type viewType)
134         {
135             Type type;
136             if (LookupHandlerType(viewType, out type))
137                 return type;
138
139             // lazy load render-view association with RenderWithAttribute (as opposed to using ExportRenderer)
140             var attribute = viewType.GetTypeInfo().GetCustomAttribute<RenderWithAttribute>();
141             if (attribute == null)
142             {
143                 Register(viewType, null); // Cache this result so we don't have to do GetCustomAttribute again
144                 return null;
145             }
146
147             type = attribute.Type;
148
149             if (type.Name.StartsWith("_", StringComparison.Ordinal))
150             {
151                 // TODO: Remove attribute2 once renderer names have been unified across all platforms
152                 var attribute2 = type.GetTypeInfo().GetCustomAttribute<RenderWithAttribute>();
153                 if (attribute2 != null)
154                     type = attribute2.Type;
155
156                 if (type.Name.StartsWith("_", StringComparison.Ordinal))
157                 {
158                     Register(viewType, null); // Cache this result so we don't work through this chain again
159                     return null;
160                 }
161             }
162
163             Register(viewType, type); // Register this so we don't have to look for the RenderWith Attibute again in the future
164
165             return type;
166         }
167
168         /// <summary>
169         /// For internal use. Return the handle type of the object
170         /// </summary>
171         /// <param name="obj">The object instance.</param>
172         /// <returns>The type of the handler.</returns>
173         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
174         [EditorBrowsable(EditorBrowsableState.Never)]
175         public Type GetHandlerTypeForObject(object obj)
176         {
177             if (obj == null)
178                 throw new ArgumentNullException(nameof(obj));
179
180             var reflectableType = obj as IReflectableType;
181             var type = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : obj.GetType();
182
183             return GetHandlerType(type);
184         }
185
186         bool LookupHandlerType(Type viewType, out Type handlerType)
187         {
188             Type type = viewType;
189
190             while (type != null)
191             {
192                 if (_handlers.ContainsKey(type))
193                 {
194                     handlerType = _handlers[type];
195                     return true;
196                 }
197
198                 type = type.GetTypeInfo().BaseType;
199             }
200
201             handlerType = null;
202             return false;
203         }
204     }
205
206     /// <summary>
207     /// For internal use
208     /// </summary>
209     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
210     [EditorBrowsable(EditorBrowsableState.Never)]
211     public static class Registrar
212     {
213         static Registrar()
214         {
215             Registered = new Registrar<IRegisterable>();
216         }
217
218         internal static Dictionary<string, Type> Effects { get; } = new Dictionary<string, Type>();
219         internal static Dictionary<string, StyleSheets.StylePropertyAttribute> StyleProperties { get; } = new Dictionary<string, StyleSheets.StylePropertyAttribute>();
220
221         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
222         [EditorBrowsable(EditorBrowsableState.Never)]
223         public static IEnumerable<Assembly> ExtraAssemblies { get; set; }
224
225         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
226         [EditorBrowsable(EditorBrowsableState.Never)]
227         public static Registrar<IRegisterable> Registered { get; internal set; }
228     }
229 }