Skip to content

Commit da79690

Browse files
author
Stedra Kristóf
committed
Add enumeration cache components
1 parent 31905c3 commit da79690

File tree

10 files changed

+395
-1
lines changed

10 files changed

+395
-1
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
namespace AutSoft.AspNetCore.Blazor.Enumeration;
2+
3+
/// <summary>
4+
/// Enumeration type items.
5+
/// </summary>
6+
/// <typeparam name="TEnum">Collection of the enumeration types.</typeparam>
7+
public class Enumeration<TEnum> where TEnum : Enum
8+
{
9+
/// <summary>
10+
/// Default constructor of the Enumeration.
11+
/// </summary>
12+
public Enumeration()
13+
{
14+
Type = default!;
15+
Items = new List<EnumerationItem>();
16+
}
17+
18+
/// <summary>
19+
/// Default constructor of the Enumeration.
20+
/// </summary>
21+
/// <param name="type">Enumeration type.</param>
22+
/// <param name="items">Items of the enumerations.</param>
23+
public Enumeration(TEnum type, List<EnumerationItem> items)
24+
{
25+
Type = type;
26+
Items = items;
27+
}
28+
29+
/// <summary>
30+
/// Enumeration type.
31+
/// </summary>
32+
public TEnum Type { get; set; }
33+
34+
/// <summary>
35+
/// Items of the enumeration.
36+
/// </summary>
37+
public List<EnumerationItem> Items { get; set; }
38+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
using AutSoft.Common.Concurrency;
2+
3+
using Microsoft.Extensions.Logging;
4+
5+
namespace AutSoft.AspNetCore.Blazor.Enumeration;
6+
7+
/// <inheritdoc />
8+
public class EnumerationCache<TEnum> : IEnumerationCache<TEnum>, IDisposable where TEnum : Enum
9+
{
10+
private readonly Dictionary<TEnum, List<EnumerationItem>> _enumerations = new();
11+
12+
private readonly AsyncLock _downloadLock = new();
13+
14+
private readonly IEnumerationService<TEnum> _enumerationClient;
15+
private readonly ILogger<EnumerationCache<TEnum>> _logger;
16+
17+
/// <summary>
18+
/// Constructor of the EnumerationCache.
19+
/// </summary>
20+
/// <param name="enumerationService">Enumeration service.</param>
21+
/// <param name="logger">Logger of the enumeration cache.</param>
22+
public EnumerationCache(IEnumerationService<TEnum> enumerationService, ILogger<EnumerationCache<TEnum>> logger)
23+
{
24+
_enumerationClient = enumerationService;
25+
_logger = logger;
26+
}
27+
28+
/// <inheritdoc />
29+
public async Task EnsureHasCachedEnumerationAsync(params TEnum[] enumerationTypes)
30+
{
31+
using (await AsyncLockContext.CreateAsync(_downloadLock))
32+
{
33+
var enumerationTypesToDownload = enumerationTypes.Where(t => !_enumerations.Any(m => m.Key.Equals(t))).ToList();
34+
if (enumerationTypesToDownload.Count == 0)
35+
return;
36+
37+
var result = await _enumerationClient.ListEnumerationsAsync(enumerationTypesToDownload);
38+
39+
foreach (var enumerationItem in result)
40+
{
41+
if (!_enumerations.ContainsKey(enumerationItem.Type))
42+
_enumerations.Add(enumerationItem.Type, enumerationItem.Items);
43+
}
44+
}
45+
}
46+
47+
private async Task TryEnsureHasCachedEnumerationAsync(params TEnum[] enumerationTypes)
48+
{
49+
try
50+
{
51+
await EnsureHasCachedEnumerationAsync(enumerationTypes);
52+
}
53+
catch (Exception e)
54+
{
55+
_logger.LogError(e, "Failed to load enumerations.");
56+
}
57+
}
58+
59+
/// <inheritdoc />
60+
public async Task<string?> ResolveDisplayNameAsync(TEnum type, int key)
61+
{
62+
await TryEnsureHasCachedEnumerationAsync(type);
63+
64+
if (!_enumerations.ContainsKey(type))
65+
return null;
66+
67+
return _enumerations[type].SingleOrDefault(i => i.Id == key)?.DisplayName;
68+
}
69+
70+
/// <inheritdoc />
71+
public async Task<List<EnumerationItem>> ResolveEnumerationItemsAsync(TEnum type)
72+
{
73+
await TryEnsureHasCachedEnumerationAsync(type);
74+
75+
if (!_enumerations.ContainsKey(type))
76+
return new List<EnumerationItem>();
77+
78+
return _enumerations[type];
79+
}
80+
81+
/// <inheritdoc />
82+
public void Dispose()
83+
{
84+
_downloadLock.Dispose();
85+
GC.SuppressFinalize(this);
86+
}
87+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
namespace AutSoft.AspNetCore.Blazor.Enumeration;
2+
3+
/// <summary>
4+
/// Enumeration item data.
5+
/// </summary>
6+
public class EnumerationItem
7+
{
8+
/// <summary>
9+
/// Default constructor of the EnumerationItem.
10+
/// </summary>
11+
public EnumerationItem()
12+
{
13+
}
14+
15+
/// <summary>
16+
/// Constructor of the EnumerationItem.
17+
/// </summary>
18+
/// <param name="key">Key of the enum item.</param>
19+
/// <param name="value">Value of the enum item.</param>
20+
public EnumerationItem(int key, string value)
21+
{
22+
Id = key;
23+
DisplayName = value;
24+
}
25+
26+
/// <summary>
27+
/// Enumeration item id.
28+
/// </summary>
29+
public int Id { get; set; }
30+
31+
/// <summary>
32+
/// Enumeration diplay name.
33+
/// </summary>
34+
public string DisplayName { get; set; } = null!;
35+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
namespace AutSoft.AspNetCore.Blazor.Enumeration;
2+
3+
/// <summary>
4+
/// Cache for enumeration types.
5+
/// </summary>
6+
/// <typeparam name="TEnum">Collection of the enumeration types.</typeparam>
7+
public interface IEnumerationCache<TEnum> where TEnum : Enum
8+
{
9+
/// <summary>
10+
/// Resolves the display name of the specified enumeration type with id.
11+
/// </summary>
12+
/// <param name="type">Enumeration type.</param>
13+
/// <param name="id">Id of the enumeration type.</param>
14+
/// <returns>Display name.</returns>
15+
Task<string?> ResolveDisplayNameAsync(TEnum type, int id);
16+
17+
/// <summary>
18+
/// Resolves enumeration items of the specified enumeration type.
19+
/// </summary>
20+
/// <param name="type">Enumeration type.</param>
21+
/// <returns>Enumeration items.</returns>
22+
Task<List<EnumerationItem>> ResolveEnumerationItemsAsync(TEnum type);
23+
24+
/// <summary>
25+
/// Caches the specified enumeration types if they are not in the cache.
26+
/// </summary>
27+
/// <param name="enumerationTypes">Enumeration types.</param>
28+
Task EnsureHasCachedEnumerationAsync(params TEnum[] enumerationTypes);
29+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace AutSoft.AspNetCore.Blazor.Enumeration;
2+
3+
/// <summary>
4+
/// Enumeration service that is used by the cache to get the values of enumeration types.
5+
/// </summary>
6+
/// <typeparam name="TEnum">Collection of the enumeration types.</typeparam>
7+
public interface IEnumerationService<TEnum> where TEnum : Enum
8+
{
9+
/// <summary>
10+
/// Lists the specified enumeration types.
11+
/// </summary>
12+
/// <param name="enumerationTypes">Enumeration types.</param>
13+
/// <returns>Values of the enumeration types.</returns>
14+
Task<List<Enumeration<TEnum>>> ListEnumerationsAsync(List<TEnum> enumerationTypes);
15+
}

src/AutSoft.AspNetCore.Blazor/ServiceCollectionExtensions.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using AutSoft.AspNetCore.Blazor.Clipboard;
22
using AutSoft.AspNetCore.Blazor.ComponentState;
3-
using AutSoft.AspNetCore.Blazor.Enumeration;
43
using AutSoft.AspNetCore.Blazor.ErrorHandling;
54
using AutSoft.AspNetCore.Blazor.Localization;
65

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using AutSoft.AspNetCore.Blazor.Enumeration;
2+
3+
using Microsoft.AspNetCore.Components;
4+
5+
using MudBlazor;
6+
7+
namespace AutSoft.Mud.Blazor.Enumeration;
8+
9+
/// <summary>
10+
/// Enumeration autocomplete.
11+
/// </summary>
12+
/// <typeparam name="T">Enumeration type.</typeparam>
13+
/// <typeparam name="TEnum">Collection of the enumeration types.</typeparam>
14+
public class EnumerationAutocomplete<T, TEnum> : MudAutocomplete<T> where TEnum : Enum
15+
{
16+
/// <summary>
17+
/// Items number to show.
18+
/// </summary>
19+
[Parameter]
20+
public int Take { get; set; } = 10;
21+
22+
/// <summary>
23+
/// Enumeration type.
24+
/// </summary>
25+
[Parameter]
26+
public TEnum Type { get; set; } = default!;
27+
28+
[Inject]
29+
private IEnumerationCache<TEnum> EnumerationCache { get; set; } = null!;
30+
31+
private List<EnumerationItem> _enumerationItems = new();
32+
33+
/// <summary>
34+
/// Default constructor of the EnumerationAutocomplete.
35+
/// </summary>
36+
public EnumerationAutocomplete()
37+
{
38+
var enumType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
39+
if (!enumType.IsEnum && enumType != typeof(int))
40+
throw new NotSupportedException("Only enum/int or nullable enum/int types are supported!");
41+
42+
ToStringFunc = (t) => t == null ? null : _enumerationItems.SingleOrDefault(d => d.Id == (int)(object)t!)?.DisplayName;
43+
44+
SearchFunc = (filter) => Task.FromResult(
45+
_enumerationItems
46+
.Where(c => string.IsNullOrEmpty(filter) || c.DisplayName.Contains(filter, StringComparison.InvariantCultureIgnoreCase))
47+
.Take(Take)
48+
.Select(c => enumType.IsEnum ? (T)Enum.ToObject(enumType, c.Id) : (T)(object)c.Id));
49+
}
50+
51+
/// <inheritdoc />
52+
public override async Task SetParametersAsync(ParameterView parameters)
53+
{
54+
await base.SetParametersAsync(parameters);
55+
56+
if (!Type.Equals(default(TEnum)))
57+
{
58+
_enumerationItems = await EnumerationCache.ResolveEnumerationItemsAsync(Type);
59+
await UpdateTextPropertyAsync(false);
60+
StateHasChanged();
61+
}
62+
}
63+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@typeparam TEnum where TEnum : Enum
2+
@inherits MudComponentBase
3+
@_displayName
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using AutSoft.AspNetCore.Blazor.Enumeration;
2+
3+
using Microsoft.AspNetCore.Components;
4+
5+
using MudBlazor;
6+
7+
namespace AutSoft.Mud.Blazor.Enumeration;
8+
9+
/// <summary>
10+
/// Enumeration display.
11+
/// </summary>
12+
/// <typeparam name="TEnum">Collection of the enumeration types.</typeparam>
13+
public partial class EnumerationDisplay<TEnum> : MudComponentBase where TEnum : Enum
14+
{
15+
/// <summary>
16+
/// Enumeration type.
17+
/// </summary>
18+
[Parameter]
19+
public TEnum Type { get; set; } = default!;
20+
21+
/// <summary>
22+
/// Enumeration type id.
23+
/// </summary>
24+
[Parameter]
25+
public int? Id { get; set; }
26+
27+
[Inject]
28+
private IEnumerationCache<TEnum> EnumerationCache { get; set; } = null!;
29+
30+
private string? _displayName;
31+
32+
/// <inheritdoc />
33+
protected override async Task OnParametersSetAsync()
34+
{
35+
await base.OnParametersSetAsync();
36+
37+
if (Type.Equals(default(TEnum)) && Id.HasValue && Id.Value != default)
38+
_displayName = await EnumerationCache.ResolveDisplayNameAsync(Type, Id.Value);
39+
else
40+
{
41+
_displayName = null;
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)