< Summary

Information
Class: MyNet.UI.ViewModels.List.CrudListViewModel<T>
Assembly: MyNet.UI
File(s): https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.UI/ViewModels/List/CrudListViewModel.cs
Tag: 323_28699572109
Line coverage
72%
Covered lines: 21
Uncovered lines: 8
Coverable lines: 29
Total lines: 142
Line coverage: 72.4%
Branch coverage
75%
Covered branches: 12
Total branches: 16
Branch coverage: 75%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)50%44100%
CanAdd()100%210%
CanEdit(...)100%210%
CanDelete(...)100%210%
AddAsync()100%22100%
EditAsync()100%22100%
DeleteAsync()100%22100%
OnItemAddedAsync(...)100%11100%
OnItemEditedAsync(...)100%210%
OnItemDeletedAsync(...)100%210%
DeleteRangeAsync()66.66%6683.33%

File(s)

https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.UI/ViewModels/List/CrudListViewModel.cs

#LineLine coverage
 1// -----------------------------------------------------------------------
 2// <copyright file="CrudListViewModel.cs" company="Stéphane ANDRE">
 3// Copyright (c) Stéphane ANDRE. All rights reserved.
 4// </copyright>
 5// -----------------------------------------------------------------------
 6
 7using System;
 8using System.Collections.Generic;
 9using System.Threading;
 10using System.Threading.Tasks;
 11using System.Windows.Input;
 12using MyNet.UI.Commands;
 13using MyNet.UI.ViewModels.List.Services;
 14
 15namespace MyNet.UI.ViewModels.List;
 16
 17/// <summary>
 18/// Provides a list view model enriched with CRUD commands.
 19/// </summary>
 20/// <typeparam name="T">The item type.</typeparam>
 21public class CrudListViewModel<T> : ListViewModel<T>
 22    where T : notnull
 23{
 24    private readonly ICrudService<T> _crudService;
 25
 26    /// <summary>
 27    /// Initializes a new instance of the <see cref="CrudListViewModel{T}"/> class.
 28    /// </summary>
 29    public CrudListViewModel(
 30        IListDataProvider<T> dataProvider,
 31        ICrudService<T> crudService,
 32        Factories.ListViewModelOptions<T>? options = null)
 2133        : base(dataProvider, options)
 34    {
 2135        _crudService = crudService ?? throw new ArgumentNullException(nameof(crudService));
 2136        var commands = (options?.CommandFactory).GetOrDefault();
 37
 38        AddCommand = commands.Create(() => AddAsync(), CanAdd);
 39        EditCommand = commands.CreateRequired<T>(item => EditAsync(item), CanEdit);
 40        DeleteCommand = commands.CreateRequired<T>(item => DeleteAsync(item), CanDelete);
 2141    }
 42
 43    /// <summary>
 44    /// Gets the command used to add an item.
 45    /// </summary>
 46    public ICommand AddCommand { get; }
 47
 48    /// <summary>
 49    /// Gets the command used to edit an item.
 50    /// </summary>
 51    public ICommand EditCommand { get; }
 52
 53    /// <summary>
 54    /// Gets the command used to delete an item.
 55    /// </summary>
 56    public ICommand DeleteCommand { get; }
 57
 58    /// <summary>
 59    /// Determines whether an add operation is currently allowed.
 60    /// </summary>
 061    protected virtual bool CanAdd() => true;
 62
 63    /// <summary>
 64    /// Determines whether an edit operation is currently allowed for a specific item.
 65    /// </summary>
 066    protected virtual bool CanEdit(T item) => true;
 67
 68    /// <summary>
 69    /// Determines whether a delete operation is currently allowed for a specific item.
 70    /// </summary>
 071    protected virtual bool CanDelete(T item) => true;
 72
 73    /// <summary>
 74    /// Executes item creation and hooks into extension points.
 75    /// </summary>
 76    protected virtual async Task AddAsync(CancellationToken cancellationToken = default)
 77    {
 678        var item = await _crudService.CreateAsync(cancellationToken).ConfigureAwait(false);
 679        if (item is not null)
 680            await OnItemAddedAsync(item, cancellationToken).ConfigureAwait(false);
 681    }
 82
 83    /// <summary>
 84    /// Executes item edition and hooks into extension points.
 85    /// </summary>
 86    protected virtual async Task EditAsync(T item, CancellationToken cancellationToken = default)
 87    {
 388        if (await _crudService.UpdateAsync(item, cancellationToken).ConfigureAwait(false))
 389            await OnItemEditedAsync(item, cancellationToken).ConfigureAwait(false);
 390    }
 91
 92    /// <summary>
 93    /// Executes item deletion and hooks into extension points.
 94    /// </summary>
 95    protected virtual async Task DeleteAsync(T item, CancellationToken cancellationToken = default)
 96    {
 397        if (await _crudService.DeleteAsync(item, cancellationToken).ConfigureAwait(false))
 398            await OnItemDeletedAsync(item, cancellationToken).ConfigureAwait(false);
 399    }
 100
 101    /// <summary>
 102    /// Extension point called when an item has been added.
 103    /// </summary>
 104    protected virtual Task OnItemAddedAsync(T item, CancellationToken cancellationToken = default)
 105    {
 3106        RequestPipelineRefresh();
 3107        return Task.CompletedTask;
 108    }
 109
 110    /// <summary>
 111    /// Extension point called when an item has been edited.
 112    /// </summary>
 113    protected virtual Task OnItemEditedAsync(T item, CancellationToken cancellationToken = default)
 114    {
 0115        RequestPipelineRefresh();
 0116        return Task.CompletedTask;
 117    }
 118
 119    /// <summary>
 120    /// Extension point called when an item has been deleted.
 121    /// </summary>
 122    protected virtual Task OnItemDeletedAsync(T item, CancellationToken cancellationToken = default)
 123    {
 0124        RequestPipelineRefresh();
 0125        return Task.CompletedTask;
 126    }
 127
 128    /// <summary>
 129    /// Deletes multiple items and calls item-level hooks for each successful deletion.
 130    /// </summary>
 131    protected virtual async Task DeleteRangeAsync(IEnumerable<T> items, CancellationToken cancellationToken = default)
 132    {
 3133        var snapshot = items as IReadOnlyList<T> ?? [.. items];
 134
 3135        if (!await _crudService.DeleteRangeAsync(snapshot, cancellationToken).ConfigureAwait(false))
 0136            return;
 137
 18138        foreach (var item in snapshot)
 6139            await OnItemDeletedAsync(item, cancellationToken).ConfigureAwait(false);
 3140    }
 141}
 142