-
Notifications
You must be signed in to change notification settings - Fork 8
/
IgnisComponentExtensions.cs
147 lines (127 loc) · 6.2 KB
/
IgnisComponentExtensions.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
145
146
147
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Ignis.Components;
public static class IgnisComponentExtensions
{
public static IServiceCollection AddIgnis(this IServiceCollection serviceCollection)
{
if (serviceCollection == null) throw new ArgumentNullException(nameof(serviceCollection));
serviceCollection.AddTransient<FrameTracker>();
serviceCollection.TryAddScoped<IContentRegistry, ContentRegistry>();
serviceCollection.TryAddSingleton<TimeProvider, TimeProviderImplementation>();
return serviceCollection;
}
#pragma warning disable ASP0006
public static void OpenAs(this RenderTreeBuilder builder, int sequence, IDynamicComponent dynamicComponent)
{
if (builder == null) throw new ArgumentNullException(nameof(builder));
switch (dynamicComponent)
{
case null:
throw new ArgumentNullException(nameof(dynamicComponent));
case { AsElement: not null, AsComponent: not null }:
throw new InvalidOperationException(
$"Cannot specify both {nameof(IDynamicComponent.AsElement)} and {nameof(IDynamicComponent.AsComponent)} for {dynamicComponent.GetType().Name}.");
case { AsElement: null, AsComponent: null }:
throw new InvalidOperationException(
$"Must specify either {nameof(IDynamicComponent.AsElement)} and {nameof(IDynamicComponent.AsComponent)} for {dynamicComponent.GetType().Name}.");
}
if (dynamicComponent.AsElement != null)
{
builder.OpenElement(sequence, dynamicComponent.AsElement);
}
else if (dynamicComponent.AsComponent != null)
{
if (dynamicComponent.AsComponent.GetInterface(nameof(IComponent)) == null)
{
throw new InvalidOperationException(
$"Invalid component type {dynamicComponent.AsComponent.Name}. Must implement {nameof(IComponent)}.");
}
builder.OpenComponent(sequence, dynamicComponent.AsComponent);
}
}
#pragma warning restore ASP0006
public static void CloseAs(this RenderTreeBuilder builder, IDynamicComponent dynamicComponent)
{
if (builder == null) throw new ArgumentNullException(nameof(builder));
switch (dynamicComponent)
{
case null:
throw new ArgumentNullException(nameof(dynamicComponent));
case { AsElement: null, AsComponent: null } or { AsElement: not null, AsComponent: not null }:
throw new InvalidOperationException(
$"Invalid dynamic component {dynamicComponent.GetType().Name}. This is probably due to a missing .OpenAs() call.");
}
if (dynamicComponent.AsElement != null)
{
builder.CloseElement();
}
else if (dynamicComponent.AsComponent != null)
{
builder.CloseComponent();
}
}
public static RenderFragment? GetChildContent<TContext, TDynamic>(this TDynamic dynamicComponent,
RenderFragment<TContext>? childContent)
where TContext : IDynamicComponent where TDynamic : IDynamicParentComponent<TContext>, TContext
{
return GetChildContent<TContext, TDynamic>(dynamicComponent, childContent?.Invoke(dynamicComponent));
}
public static RenderFragment? GetChildContent<TContext, TDynamic>(this TDynamic dynamicComponent,
RenderFragment? childContent)
where TContext : IDynamicComponent where TDynamic : IDynamicParentComponent<TContext>, TContext
{
switch (dynamicComponent)
{
case null:
throw new ArgumentNullException(nameof(dynamicComponent));
case { AsElement: null, AsComponent: null } or { AsElement: not null, AsComponent: not null }:
throw new InvalidOperationException(
$"Invalid dynamic component {dynamicComponent.GetType().Name}. This is probably due to a missing .OpenAs() call.");
}
return dynamicComponent._ != null ? dynamicComponent._.Invoke(dynamicComponent) : childContent;
}
public static void AddChildContentFor<TContext, TDynamic>(this RenderTreeBuilder builder, int sequence,
TDynamic dynamicComponent, RenderFragment? childContent)
where TContext : IDynamicComponent where TDynamic : IDynamicParentComponent<TContext>, TContext
{
AddContentFor(builder, sequence, dynamicComponent,
GetChildContent<TContext, TDynamic>(dynamicComponent, childContent));
}
#pragma warning disable ASP0006
public static void AddContentFor(this RenderTreeBuilder builder, int sequence, IDynamicComponent dynamicComponent,
RenderFragment? content)
{
if (builder == null) throw new ArgumentNullException(nameof(builder));
switch (dynamicComponent)
{
case null:
throw new ArgumentNullException(nameof(dynamicComponent));
case { AsElement: null, AsComponent: null } or { AsElement: not null, AsComponent: not null }:
throw new InvalidOperationException(
$"Invalid dynamic component {dynamicComponent.GetType().Name}. This is probably due to a missing .OpenAs() call.");
}
if (content == null) return;
if (dynamicComponent.AsElement != null)
{
builder.AddContent(sequence, content);
}
else if (dynamicComponent.AsComponent != null)
{
builder.AddAttribute(sequence, "ChildContent", content);
}
}
#pragma warning restore ASP0006
public static ElementReference? TryProvideElementReference(this IDynamicComponent dynamicComponent)
{
if (dynamicComponent == null) throw new ArgumentNullException(nameof(dynamicComponent));
return dynamicComponent.Component switch
{
IDynamicParentComponent component => component.TryProvideElementReference(),
IElementReferenceProvider elementReferenceProvider => elementReferenceProvider.Element,
_ => dynamicComponent.Element
};
}
}