forked from dotnet/maui
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRegistrar.cs
144 lines (118 loc) · 3.01 KB
/
Registrar.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace Microsoft.Maui
{
public static class Registrar
{
public static Registrar<IView, IViewHandler> Handlers { get; private set; }
static Registrar()
{
Handlers = new Registrar<IView, IViewHandler>();
}
}
public class Registrar<TType, TTypeRender>
where TTypeRender : class
{
internal Dictionary<Type, Type> _handler = new Dictionary<Type, Type>();
internal Dictionary<Type, Func<Type, IViewHandler>> _handlerFactories = new Dictionary<Type, Func<Type, IViewHandler>>();
#nullable enable
public void Register<TView, TRender>()
where TView : TType
where TRender : TTypeRender
{
Register(typeof(TView), typeof(TRender));
}
public void Register(Type view, Type handler)
{
_handlerFactories.Remove(view);
_handler[view] = handler;
}
public void Register(Type view, Func<Type, IViewHandler> factory)
{
_handler.Remove(view);
_handlerFactories[view] = factory;
}
public void Register<TView>(Func<Type, IViewHandler> factory)
where TView : TType
{
Register(typeof(TView), factory);
}
public TTypeRender GetHandler<T>()
{
return GetHandler(typeof(T));
}
internal List<KeyValuePair<Type, Type>> GetViewType(Type type) =>
_handler.Where(x => isType(x.Value, type)).ToList();
bool isType(Type type, Type type2)
{
if (type == type2)
return true;
if (!type.IsGenericType)
return false;
var paramerter = type.GetGenericArguments();
return paramerter[0] == type2;
}
public TTypeRender GetHandler(Type type)
{
List<Type> types = new List<Type> { type };
Type? baseType = type.BaseType;
while (baseType != null)
{
types.Add(baseType);
baseType = baseType.BaseType;
}
foreach (var t in types)
{
var renderer = GetRenderer(t);
if (renderer != null)
return renderer;
}
throw new Exception($"Handler not found for {type}");
}
public Type GetRendererType(Type type)
{
List<Type> types = new List<Type> { type };
Type? baseType = type.BaseType;
while (baseType != null)
{
types.Add(baseType);
baseType = baseType.BaseType;
}
foreach (var t in types)
{
if (_handler.TryGetValue(t, out var returnType))
return returnType;
}
throw new Exception($"Renderer Type not found {type}");
}
TTypeRender? GetRenderer(Type type)
{
if (_handlerFactories.TryGetValue(type, out var handlerFactory))
{
var newObject = handlerFactory?.Invoke(type) as TTypeRender;
if (newObject != null)
return newObject;
}
if (!_handler.TryGetValue(type, out var handler))
{
return default(TTypeRender);
}
try
{
var newObject = Activator.CreateInstance(handler);
if (newObject == null)
throw new ArgumentException($"No Handler found for type: {type}", nameof(type));
return (TTypeRender)newObject;
}
catch (Exception)
{
if (Debugger.IsAttached)
throw;
}
return default(TTypeRender);
}
}
#nullable disable
}