-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTriggerMapper.cs
More file actions
79 lines (70 loc) · 4.29 KB
/
Copy pathTriggerMapper.cs
File metadata and controls
79 lines (70 loc) · 4.29 KB
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
using System.Reflection;
using InvvardDev.Ifttt.Contracts;
using InvvardDev.Ifttt.Models.Core;
using InvvardDev.Ifttt.Models.Trigger;
using InvvardDev.Ifttt.Toolkit.Attributes;
namespace InvvardDev.Ifttt.Reflection;
internal class TriggerMapper(
[FromKeyedServices(ProcessorKind.Trigger)] IProcessorService triggerService,
[FromKeyedServices(nameof(TriggerAttributeLookup))] IAttributeLookup triggerAttributeLookup,
[FromKeyedServices(nameof(TriggerFieldsAttributeLookup))] IAttributeLookup triggerFieldsAttributeLookup,
ILogger<TriggerMapper> logger) : ITriggerMapper
{
public async Task MapTriggerProcessors(CancellationToken stoppingToken)
=> await MapAttribute<TriggerAttribute>(triggerAttributeLookup.GetAnnotatedTypes(),
async (triggerSlug, type) => await triggerService.GetProcessor(triggerSlug) switch
{
{ } existingProcessorTree when existingProcessorTree.ProcessorType == type
=> true,
{ } existingProcessorTree when existingProcessorTree.ProcessorType != type
=> throw new
InvalidOperationException($"Conflict: 'Trigger' processor with slug '{triggerSlug}' already exists (Type is '{existingProcessorTree.ProcessorType}')."),
_ => false,
},
stoppingToken);
public async Task MapTriggerFields(CancellationToken stoppingToken)
=> await MapAttribute<TriggerFieldsAttribute>(triggerFieldsAttributeLookup.GetAnnotatedTypes(),
async (triggerSlug, _) => await triggerService.Exists(triggerSlug) switch
{
true => true,
false => throw new InvalidOperationException($"There is no trigger with slug '{triggerSlug}' registered.")
},
stoppingToken);
private async Task MapTriggerFieldProperties(string parentSlug, Type parentType)
{
var properties = parentType.GetProperties();
foreach (var property in properties)
{
if (property.GetCustomAttribute<DataFieldAttribute>() is { } triggerFieldAttribute)
{
await triggerService.AddDataField(parentSlug, triggerFieldAttribute.Slug, property.PropertyType);
}
}
}
private async Task<TriggerMapper> MapAttribute<TAttribute>(IEnumerable<Type> types, Func<string, Type, Task<bool>> processorExists, CancellationToken stoppingToken = default)
where TAttribute : ProcessorAttributeBase
{
stoppingToken.ThrowIfCancellationRequested();
try
{
foreach (var type in types)
{
if (type.GetCustomAttribute<TAttribute>() is not { } attribute) continue;
if (!await processorExists(attribute.Slug, type))
{
await triggerService.AddOrUpdateProcessor(new ProcessorTree(attribute.Slug, type, ProcessorKind.Trigger));
}
await MapTriggerFieldProperties(attribute.Slug, type);
}
}
catch (OperationCanceledException ocex)
{
logger.LogInformation(ocex, "Mapping for attribute '{AttributeType}' was cancelled.", typeof(TAttribute));
}
catch (Exception ex)
{
logger.LogError(ex, "Mapping for attribute '{AttributeType}' has failed.", typeof(TAttribute));
}
return this;
}
}