Refactor (#94)

This commit is contained in:
Alexey Golub
2021-03-21 09:54:00 +02:00
committed by GitHub
parent 58df63a7ad
commit 7d3d79b861
228 changed files with 10480 additions and 8968 deletions

View File

@@ -1,45 +1,45 @@
using System;
using System.Threading.Tasks;
using CliFx.Attributes;
using CliFx.Demo.Internal;
using CliFx.Demo.Models;
using CliFx.Demo.Services;
using CliFx.Demo.Domain;
using CliFx.Demo.Utils;
using CliFx.Exceptions;
using CliFx.Infrastructure;
namespace CliFx.Demo.Commands
{
[Command("book add", Description = "Add a book to the library.")]
public partial class BookAddCommand : ICommand
{
private readonly LibraryService _libraryService;
private readonly LibraryProvider _libraryProvider;
[CommandParameter(0, Name = "title", Description = "Book title.")]
public string Title { get; set; } = "";
public string Title { get; init; } = "";
[CommandOption("author", 'a', IsRequired = true, Description = "Book author.")]
public string Author { get; set; } = "";
public string Author { get; init; } = "";
[CommandOption("published", 'p', Description = "Book publish date.")]
public DateTimeOffset Published { get; set; } = CreateRandomDate();
public DateTimeOffset Published { get; init; } = CreateRandomDate();
[CommandOption("isbn", 'n', Description = "Book ISBN.")]
public Isbn Isbn { get; set; } = CreateRandomIsbn();
public Isbn Isbn { get; init; } = CreateRandomIsbn();
public BookAddCommand(LibraryService libraryService)
public BookAddCommand(LibraryProvider libraryProvider)
{
_libraryService = libraryService;
_libraryProvider = libraryProvider;
}
public ValueTask ExecuteAsync(IConsole console)
{
if (_libraryService.GetBook(Title) != null)
throw new CommandException("Book already exists.", 1);
if (_libraryProvider.TryGetBook(Title) is not null)
throw new CommandException("Book already exists.", 10);
var book = new Book(Title, Author, Published, Isbn);
_libraryService.AddBook(book);
_libraryProvider.AddBook(book);
console.Output.WriteLine("Book added.");
console.RenderBook(book);
console.Output.WriteBook(book);
return default;
}
@@ -56,13 +56,15 @@ namespace CliFx.Demo.Commands
Random.Next(1, 23),
Random.Next(1, 59),
Random.Next(1, 59),
TimeSpan.Zero);
TimeSpan.Zero
);
private static Isbn CreateRandomIsbn() => new(
Random.Next(0, 999),
Random.Next(0, 99),
Random.Next(0, 99999),
Random.Next(0, 99),
Random.Next(0, 9));
Random.Next(0, 9)
);
}
}

View File

@@ -1,32 +1,33 @@
using System.Threading.Tasks;
using CliFx.Attributes;
using CliFx.Demo.Internal;
using CliFx.Demo.Services;
using CliFx.Demo.Domain;
using CliFx.Demo.Utils;
using CliFx.Exceptions;
using CliFx.Infrastructure;
namespace CliFx.Demo.Commands
{
[Command("book", Description = "View, list, add or remove books.")]
[Command("book", Description = "Retrieve a book from the library.")]
public class BookCommand : ICommand
{
private readonly LibraryService _libraryService;
private readonly LibraryProvider _libraryProvider;
[CommandParameter(0, Name = "title", Description = "Book title.")]
public string Title { get; set; } = "";
[CommandParameter(0, Name = "title", Description = "Title of the book to retrieve.")]
public string Title { get; init; } = "";
public BookCommand(LibraryService libraryService)
public BookCommand(LibraryProvider libraryProvider)
{
_libraryService = libraryService;
_libraryProvider = libraryProvider;
}
public ValueTask ExecuteAsync(IConsole console)
{
var book = _libraryService.GetBook(Title);
var book = _libraryProvider.TryGetBook(Title);
if (book == null)
throw new CommandException("Book not found.", 1);
if (book is null)
throw new CommandException("Book not found.", 10);
console.RenderBook(book);
console.Output.WriteBook(book);
return default;
}

View File

@@ -1,34 +1,34 @@
using System.Threading.Tasks;
using CliFx.Attributes;
using CliFx.Demo.Internal;
using CliFx.Demo.Services;
using CliFx.Demo.Domain;
using CliFx.Demo.Utils;
using CliFx.Infrastructure;
namespace CliFx.Demo.Commands
{
[Command("book list", Description = "List all books in the library.")]
public class BookListCommand : ICommand
{
private readonly LibraryService _libraryService;
private readonly LibraryProvider _libraryProvider;
public BookListCommand(LibraryService libraryService)
public BookListCommand(LibraryProvider libraryProvider)
{
_libraryService = libraryService;
_libraryProvider = libraryProvider;
}
public ValueTask ExecuteAsync(IConsole console)
{
var library = _libraryService.GetLibrary();
var library = _libraryProvider.GetLibrary();
var isFirst = true;
foreach (var book in library.Books)
for (var i = 0; i < library.Books.Count; i++)
{
// Margin
if (!isFirst)
// Add margin
if (i != 0)
console.Output.WriteLine();
isFirst = false;
// Render book
console.RenderBook(book);
var book = library.Books[i];
console.Output.WriteBook(book);
}
return default;

View File

@@ -1,31 +1,32 @@
using System.Threading.Tasks;
using CliFx.Attributes;
using CliFx.Demo.Services;
using CliFx.Demo.Domain;
using CliFx.Exceptions;
using CliFx.Infrastructure;
namespace CliFx.Demo.Commands
{
[Command("book remove", Description = "Remove a book from the library.")]
public class BookRemoveCommand : ICommand
{
private readonly LibraryService _libraryService;
private readonly LibraryProvider _libraryProvider;
[CommandParameter(0, Name = "title", Description = "Book title.")]
public string Title { get; set; } = "";
[CommandParameter(0, Name = "title", Description = "Title of the book to remove.")]
public string Title { get; init; } = "";
public BookRemoveCommand(LibraryService libraryService)
public BookRemoveCommand(LibraryProvider libraryProvider)
{
_libraryService = libraryService;
_libraryProvider = libraryProvider;
}
public ValueTask ExecuteAsync(IConsole console)
{
var book = _libraryService.GetBook(Title);
var book = _libraryProvider.TryGetBook(Title);
if (book == null)
throw new CommandException("Book not found.", 1);
if (book is null)
throw new CommandException("Book not found.", 10);
_libraryService.RemoveBook(book);
_libraryProvider.RemoveBook(book);
console.Output.WriteLine($"Book {Title} removed.");

View File

@@ -1,6 +1,6 @@
using System;
namespace CliFx.Demo.Models
namespace CliFx.Demo.Domain
{
public class Book
{

View File

@@ -1,6 +1,6 @@
using System;
namespace CliFx.Demo.Models
namespace CliFx.Demo.Domain
{
public partial class Isbn
{

View File

@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace CliFx.Demo.Domain
{
public partial class Library
{
public IReadOnlyList<Book> Books { get; }
public Library(IReadOnlyList<Book> books)
{
Books = books;
}
public Library WithBook(Book book)
{
var books = Books.ToList();
books.Add(book);
return new Library(books);
}
public Library WithoutBook(Book book)
{
var books = Books.Where(b => b != book).ToArray();
return new Library(books);
}
}
public partial class Library
{
public static Library Empty { get; } = new(Array.Empty<Book>());
}
}

View File

@@ -1,13 +1,12 @@
using System.IO;
using System.Linq;
using CliFx.Demo.Models;
using Newtonsoft.Json;
namespace CliFx.Demo.Services
namespace CliFx.Demo.Domain
{
public class LibraryService
public class LibraryProvider
{
private string StorageFilePath => Path.Combine(Directory.GetCurrentDirectory(), "Data.json");
private static string StorageFilePath { get; } = Path.Combine(Directory.GetCurrentDirectory(), "Library.json");
private void StoreLibrary(Library library)
{
@@ -25,7 +24,7 @@ namespace CliFx.Demo.Services
return JsonConvert.DeserializeObject<Library>(data);
}
public Book? GetBook(string title) => GetLibrary().Books.FirstOrDefault(b => b.Title == title);
public Book? TryGetBook(string title) => GetLibrary().Books.FirstOrDefault(b => b.Title == title);
public void AddBook(Book book)
{

View File

@@ -1,29 +0,0 @@
using System;
using CliFx.Demo.Models;
namespace CliFx.Demo.Internal
{
internal static class Extensions
{
public static void RenderBook(this IConsole console, Book book)
{
// Title
console.WithForegroundColor(ConsoleColor.White, () => console.Output.WriteLine(book.Title));
// Author
console.Output.Write(" ");
console.Output.Write("Author: ");
console.WithForegroundColor(ConsoleColor.White, () => console.Output.WriteLine(book.Author));
// Published
console.Output.Write(" ");
console.Output.Write("Published: ");
console.WithForegroundColor(ConsoleColor.White, () => console.Output.WriteLine($"{book.Published:d}"));
// ISBN
console.Output.Write(" ");
console.Output.Write("ISBN: ");
console.WithForegroundColor(ConsoleColor.White, () => console.Output.WriteLine(book.Isbn));
}
}
}

View File

@@ -1,22 +0,0 @@
using System.Linq;
namespace CliFx.Demo.Models
{
public static class Extensions
{
public static Library WithBook(this Library library, Book book)
{
var books = library.Books.ToList();
books.Add(book);
return new Library(books);
}
public static Library WithoutBook(this Library library, Book book)
{
var books = library.Books.Where(b => b != book).ToArray();
return new Library(books);
}
}
}

View File

@@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
namespace CliFx.Demo.Models
{
public partial class Library
{
public IReadOnlyList<Book> Books { get; }
public Library(IReadOnlyList<Book> books)
{
Books = books;
}
}
public partial class Library
{
public static Library Empty { get; } = new(Array.Empty<Book>());
}
}

View File

@@ -1,7 +1,7 @@
using System;
using System.Threading.Tasks;
using CliFx.Demo.Commands;
using CliFx.Demo.Services;
using CliFx.Demo.Domain;
using Microsoft.Extensions.DependencyInjection;
namespace CliFx.Demo
@@ -14,7 +14,7 @@ namespace CliFx.Demo
var services = new ServiceCollection();
// Register services
services.AddSingleton<LibraryService>();
services.AddSingleton<LibraryProvider>();
// Register commands
services.AddTransient<BookCommand>();
@@ -27,6 +27,7 @@ namespace CliFx.Demo
public static async Task<int> Main() =>
await new CliApplicationBuilder()
.SetDescription("Demo application showcasing CliFx features.")
.AddCommandsFromThisAssembly()
.UseTypeActivator(GetServiceProvider().GetRequiredService)
.Build()

View File

@@ -2,6 +2,4 @@
Sample command line interface for managing a library of books.
This demo project shows basic CliFx functionality such as command routing, argument parsing, autogenerated help text, and some other things.
You can get a list of available commands by running `CliFx.Demo --help`.
This demo project showcases basic CliFx functionality such as command routing, argument parsing, autogenerated help text.

View File

@@ -0,0 +1,37 @@
using System;
using CliFx.Demo.Domain;
using CliFx.Infrastructure;
namespace CliFx.Demo.Utils
{
internal static class ConsoleExtensions
{
public static void WriteBook(this ConsoleWriter writer, Book book)
{
// Title
using (writer.Console.WithForegroundColor(ConsoleColor.White))
writer.WriteLine(book.Title);
// Author
writer.Write(" ");
writer.Write("Author: ");
using (writer.Console.WithForegroundColor(ConsoleColor.White))
writer.WriteLine(book.Author);
// Published
writer.Write(" ");
writer.Write("Published: ");
using (writer.Console.WithForegroundColor(ConsoleColor.White))
writer.WriteLine($"{book.Published:d}");
// ISBN
writer.Write(" ");
writer.Write("ISBN: ");
using (writer.Console.WithForegroundColor(ConsoleColor.White))
writer.WriteLine(book.Isbn);
}
}
}