-
Notifications
You must be signed in to change notification settings - Fork 795
/
DistinctValuesRegistration.cs
118 lines (98 loc) · 4.74 KB
/
DistinctValuesRegistration.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
using Microsoft.Extensions.DependencyInjection;
namespace Serenity.Web;
/// <summary>
/// Contains helper methods for distinct values scripts
/// </summary>
public class DistinctValuesRegistration
{
/// <summary>
/// Creates and registers dynamic scripts for row properties with
/// <see cref="DistinctValuesEditorAttribute"/>
/// </summary>
/// <param name="scriptManager">Dynamic script manager</param>
/// <param name="typeSource">Type source</param>
/// <param name="serviceProvider">Service provider</param>
/// <exception cref="ArgumentNullException">Script manager, type source or
/// service provider is null</exception>
/// <exception cref="Exception">DistinctValuesAttribute is placed on a non-row type</exception>
public static void RegisterDistinctValueScripts(IDynamicScriptManager scriptManager,
ITypeSource typeSource, IServiceProvider serviceProvider)
{
ArgumentNullException.ThrowIfNull(scriptManager);
ArgumentNullException.ThrowIfNull(typeSource);
ArgumentNullException.ThrowIfNull(serviceProvider);
var list = new List<DistinctValuesEditorAttribute>();
foreach (var type in typeSource.GetTypes())
{
bool isRow = typeof(IRow).IsAssignableFrom(type) &&
!type.IsInterface;
if (!isRow &&
type.GetCustomAttribute<FormScriptAttribute>() == null &&
type.GetCustomAttribute<ColumnsScriptAttribute>() == null)
{
continue;
}
if (isRow &&
type.IsAbstract)
continue;
foreach (var property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
var attr = property.GetCustomAttribute<DistinctValuesEditorAttribute>();
if (attr == null)
continue;
if (attr.RowType != null)
{
if (attr.RowType.IsInterface ||
attr.RowType.IsAbstract ||
!typeof(IRow).IsAssignableFrom(attr.RowType))
{
throw new Exception("DistinctValuesEditor can't be used with type: " +
attr.RowType.FullName + " as it is not a row type. This attribute is specified " +
"on " + property.Name + " property of " + type.FullName);
}
attr.PropertyName = string.IsNullOrEmpty(attr.PropertyName) ? property.Name :
attr.PropertyName;
}
else
{
if (!isRow)
{
var basedOnRowAttr = type.GetCustomAttribute<BasedOnRowAttribute>();
if (basedOnRowAttr == null || basedOnRowAttr.RowType == null ||
basedOnRowAttr.RowType.IsAbstract ||
basedOnRowAttr.RowType.IsInterface ||
!typeof(IRow).IsAssignableFrom(basedOnRowAttr.RowType))
{
throw new Exception("Invalid usage of DistinctValuesEditor attribute on " +
"property " + property.Name + " of " + type.FullName + ". " +
"RowType has to be specified!");
}
attr.RowType = basedOnRowAttr.RowType;
}
else
attr.RowType = type;
attr.PropertyName = string.IsNullOrEmpty(attr.PropertyName) ? property.Name :
attr.PropertyName;
}
list.Add(attr);
}
}
var byRowProperty = list.ToLookup(x => new Tuple<Type, string>(x.RowType, x.PropertyName));
foreach (var key in byRowProperty)
{
var row = (IRow)Activator.CreateInstance(key.Key.Item1);
var script = (LookupScript)ActivatorUtilities.CreateInstance(serviceProvider,
typeof(DistinctValuesScript<>).MakeGenericType(key.Key.Item1),
[key.Key.Item2]);
script.LookupKey = "Distinct." + row.GetFields().LocalTextPrefix + "." +
key.Key.Item2;
var withPermission = key.FirstOrDefault(x => !string.IsNullOrEmpty(x.Permission));
if (withPermission != null)
script.Permission = withPermission.Permission;
var withExpiration = key.FirstOrDefault(x => x.Expiration != 0);
if (withExpiration != null)
script.Expiration = TimeSpan.FromSeconds(withExpiration.Expiration);
scriptManager.Register(script.ScriptName, script);
}
}
}