From c897f431047a6123f16ce2a0ee9e45602d72fb40 Mon Sep 17 00:00:00 2001 From: Insire Date: Sat, 6 Jan 2018 23:54:16 +0100 Subject: [PATCH 01/16] initial cleanup for virtualization, added base classes for virtualization and caching --- src/Maple.Core/Maple.Core.csproj | 18 +- .../ViewModels/BaseDataListViewModel.cs | 6 +- .../ViewModels/BaseDataViewModel.cs | 4 +- .../ViewModels/ValidableBaseDataViewModel.cs | 6 +- .../Virtualization/Base/BaseDataProvider.cs | 50 +++++ .../Virtualization/Base/IDataProvider.cs | 14 ++ .../Base/IDataVirtualizationItemProvider.cs | 10 + .../DataVirtualizationCollectionView.cs | 72 +++++++ .../Virtualization/VirtualizationViewModel.cs | 96 ++++++++++ .../VirtualizationViewModelState.cs | 14 ++ .../Services/Caching/ICachingService.cs | 11 ++ .../Services/Caching/MemoryCacheService.cs | 83 +++++++++ .../Caching/SimpleInMemoryCacheService.cs | 19 ++ .../Services/Caching/WeakReferenceCache.cs | 41 ++++ .../{ => Logging}/DetailLoggingService.cs | 2 +- .../{ => Logging}/LogNotifcationService.cs | 3 + .../Services/{ => Logging}/LoggingService.cs | 2 +- .../DB/CreateSeedDatabaseIfNotExists.cs | 176 +++++++++--------- src/Maple.Data/DB/PlaylistContext.cs | 2 - .../Repository/Base/IMediaItemRepository.cs | 2 +- .../Repository/Base/IMediaPlayerRepository.cs | 2 +- .../Repository/Base/IPlaylistRepository.cs | 2 +- .../Base/MaplePlaylistRepository.cs | 79 ++++---- .../Repository/MediaItemRepository.cs | 16 +- .../Repository/MediaPlayerRepository.cs | 38 ++-- .../Repository/PlaylistRepository.cs | 8 +- src/Maple.Domain/Interfaces/IBaseObject.cs | 4 +- .../Interfaces/IMapleRepository.cs | 14 +- src/Maple.Domain/Maple.Domain.csproj | 2 - src/Maple.Domain/Models/Base/BaseObject.cs | 7 +- src/Maple.Domain/Models/MediaItemModel.cs | 4 +- src/Maple.Domain/Models/MediaPlayerModel.cs | 2 +- src/Maple.Domain/Models/OptionModel.cs | 16 -- src/Maple.Domain/Models/PlaylistModel.cs | 2 +- src/Maple.Domain/Models/RawModel.cs | 7 - src/Maple/Interfaces/IBaseMapper.cs | 6 +- src/Maple/Interfaces/IMediaItemMapper.cs | 2 +- src/Maple/Interfaces/IMediaPlayerMapper.cs | 2 +- src/Maple/Interfaces/IPlaylistMapper.cs | 2 +- src/Maple/ViewModels/MediaItems/MediaItem.cs | 2 +- src/Maple/ViewModels/MediaItems/MediaItems.cs | 2 +- .../ViewModels/MediaPlayer/MediaPlayer.cs | 2 +- .../ViewModels/MediaPlayer/MediaPlayers.cs | 2 +- src/Maple/ViewModels/Playlists/Playlist.cs | 2 +- src/Maple/ViewModels/Playlists/Playlists.cs | 2 +- 45 files changed, 629 insertions(+), 229 deletions(-) create mode 100644 src/Maple.Core/Observables/Virtualization/Base/BaseDataProvider.cs create mode 100644 src/Maple.Core/Observables/Virtualization/Base/IDataProvider.cs create mode 100644 src/Maple.Core/Observables/Virtualization/Base/IDataVirtualizationItemProvider.cs create mode 100644 src/Maple.Core/Observables/Virtualization/DataVirtualizationCollectionView.cs create mode 100644 src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs create mode 100644 src/Maple.Core/Observables/Virtualization/VirtualizationViewModelState.cs create mode 100644 src/Maple.Core/Services/Caching/ICachingService.cs create mode 100644 src/Maple.Core/Services/Caching/MemoryCacheService.cs create mode 100644 src/Maple.Core/Services/Caching/SimpleInMemoryCacheService.cs create mode 100644 src/Maple.Core/Services/Caching/WeakReferenceCache.cs rename src/Maple.Core/Services/{ => Logging}/DetailLoggingService.cs (93%) rename src/Maple.Core/Services/{ => Logging}/LogNotifcationService.cs (93%) rename src/Maple.Core/Services/{ => Logging}/LoggingService.cs (99%) delete mode 100644 src/Maple.Domain/Models/OptionModel.cs delete mode 100644 src/Maple.Domain/Models/RawModel.cs diff --git a/src/Maple.Core/Maple.Core.csproj b/src/Maple.Core/Maple.Core.csproj index e37cb5a..c669c5b 100644 --- a/src/Maple.Core/Maple.Core.csproj +++ b/src/Maple.Core/Maple.Core.csproj @@ -55,6 +55,7 @@ + @@ -129,6 +130,12 @@ + + + + + + @@ -147,11 +154,14 @@ - + + + + - + @@ -159,10 +169,11 @@ - + + @@ -190,5 +201,6 @@ Maple.Localization + \ No newline at end of file diff --git a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs index 0b3949d..0b71157 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs @@ -15,9 +15,9 @@ namespace Maple.Core /// a wrapper class implementing /// a DTO implementing /// - public abstract class BaseDataListViewModel : BaseListViewModel, ILoadableViewModel - where TViewModel : BaseDataViewModel, ISequence - where TModel : class, IBaseObject + public abstract class BaseDataListViewModel : BaseListViewModel, ILoadableViewModel + where TViewModel : BaseDataViewModel, ISequence + where TModel : class, IBaseObject { protected readonly ISequenceService _sequenceProvider; protected readonly ILocalizationService _translationService; diff --git a/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs index b3fbbd4..3cf9535 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs @@ -4,8 +4,8 @@ namespace Maple.Core { - public abstract class BaseDataViewModel : BaseViewModel - where TModel : class, IBaseObject + public abstract class BaseDataViewModel : BaseViewModel + where TModel : class, IBaseObject { protected ChangeTracker ChangeTracker { get; } protected bool SkipChangeTracking { get; set; } diff --git a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs index 9cd4649..39c5606 100644 --- a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs @@ -12,9 +12,9 @@ namespace Maple.Core { - public abstract class ValidableBaseDataViewModel : BaseDataViewModel, INotifyDataErrorInfo - where TViewModel : BaseDataViewModel, ISequence - where TModel : class, IBaseObject + public abstract class ValidableBaseDataViewModel : BaseDataViewModel, INotifyDataErrorInfo + where TViewModel : BaseDataViewModel, ISequence + where TModel : class, IBaseObject { protected bool SkipValidation { get; set; } diff --git a/src/Maple.Core/Observables/Virtualization/Base/BaseDataProvider.cs b/src/Maple.Core/Observables/Virtualization/Base/BaseDataProvider.cs new file mode 100644 index 0000000..8566299 --- /dev/null +++ b/src/Maple.Core/Observables/Virtualization/Base/BaseDataProvider.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using Maple.Localization.Properties; + +namespace Maple.Core +{ + public abstract class BaseDataProvider : IDataProvider + where TViewModel : class + { + private readonly IDictionary _cache; + private readonly Func _viewModelFactory; + + protected BaseDataProvider(Func viewModelFactory, IDictionary cache) + { + _cache = cache ?? throw new ArgumentNullException(nameof(cache), $"{nameof(cache)} {Resources.IsRequired}"); + _viewModelFactory = viewModelFactory ?? throw new ArgumentNullException(nameof(viewModelFactory), $"{nameof(viewModelFactory)} {Resources.IsRequired}"); + } + + public void Chunk(IEnumerable Ids) + { + foreach (var id in Ids) + { + if (_cache.ContainsKey(id)) + continue; + + _cache.Add(id, InternalGet(id)); + } + } + + public TViewModel Get(TPrimaryKeyType id) + { + return _cache[id]; + } + + private TViewModel InternalGet(TPrimaryKeyType id) + { + return _viewModelFactory(id); + } + + public void Clear() + { + _cache.Clear(); + } + + public void Remove(TPrimaryKeyType id) + { + _cache.Remove(id); + } + } +} diff --git a/src/Maple.Core/Observables/Virtualization/Base/IDataProvider.cs b/src/Maple.Core/Observables/Virtualization/Base/IDataProvider.cs new file mode 100644 index 0000000..8f6bd91 --- /dev/null +++ b/src/Maple.Core/Observables/Virtualization/Base/IDataProvider.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Maple.Core +{ + public interface IDataProvider + { + T Get(TPrimaryKeyType id); + + void Chunk(IEnumerable Ids); + + void Clear(); + void Remove(TPrimaryKeyType id); + } +} diff --git a/src/Maple.Core/Observables/Virtualization/Base/IDataVirtualizationItemProvider.cs b/src/Maple.Core/Observables/Virtualization/Base/IDataVirtualizationItemProvider.cs new file mode 100644 index 0000000..0fdd2bb --- /dev/null +++ b/src/Maple.Core/Observables/Virtualization/Base/IDataVirtualizationItemProvider.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace Maple.Core +{ + public interface IDataVirtualizationItemProvider + { + void ExtendItems(IEnumerable items); + void DeflateItem(object item); + } +} diff --git a/src/Maple.Core/Observables/Virtualization/DataVirtualizationCollectionView.cs b/src/Maple.Core/Observables/Virtualization/DataVirtualizationCollectionView.cs new file mode 100644 index 0000000..aff2cb4 --- /dev/null +++ b/src/Maple.Core/Observables/Virtualization/DataVirtualizationCollectionView.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.Caching; +using System.Windows.Data; +using System.Windows.Threading; + +namespace Maple.Core +{ + public class VirtualizationListViewModel : ListCollectionView + { + private readonly IDataVirtualizationItemProvider _sponsor; + private readonly HashSet _deferredItems; + private readonly MemoryCache _cache; + private readonly CacheItemPolicy _policy; + + private bool _isDeferred; + + public VirtualizationListViewModel(IList list) + : base(list) + { + _deferredItems = new HashSet(); + _sponsor = list as IDataVirtualizationItemProvider; + _cache = new MemoryCache(nameof(VirtualizationListViewModel)); + _policy = new CacheItemPolicy() + { + SlidingExpiration = TimeSpan.FromSeconds(3), + Priority = CacheItemPriority.Default, + RemovedCallback = new CacheEntryRemovedCallback(CacheRemovedCallback) + }; + } + + public void CacheRemovedCallback(CacheEntryRemovedArguments arguments) + { + _sponsor.DeflateItem(arguments.CacheItem.Value); + } + + public override object GetItemAt(int index) + { + if (!_isDeferred) + { + _deferredItems.Clear(); + + Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)LoadDeferredItems); + + _isDeferred = true; + } + + var item = base.GetItemAt(index); + if (!_deferredItems.Contains(item)) + _deferredItems.Add(item); + + return item; + } + + private void LoadDeferredItems() + { + var uniqueSet = new HashSet(); + foreach (var item in _deferredItems) + { + var hashCode = item.GetHashCode(); + if (!_cache.Contains(hashCode.ToString())) + uniqueSet.Add(item); + + _cache.Add(new CacheItem(hashCode.ToString(), item), _policy); + } + + _sponsor.ExtendItems(uniqueSet); + _isDeferred = false; + } + } +} diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs new file mode 100644 index 0000000..131ed3c --- /dev/null +++ b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs @@ -0,0 +1,96 @@ +using System; +using System.Windows.Input; +using Maple.Domain; +using Maple.Localization.Properties; + +namespace Maple.Core +{ + public sealed class VirtualizationViewModel : ObservableObject + where TModel : class, IBaseObject + { + private readonly IDataProvider, TKeyDataType> _dataProvider; + + private TKeyDataType _id; + public TKeyDataType Id + { + get { return _id; } + private set { SetValue(ref _id, value); } + } + + private bool _isExtended; + public bool IsExtended + { + get { return _isExtended; } + private set { SetValue(ref _isExtended, value); } + } + + private VirtualizationViewModelState _state; + public VirtualizationViewModelState State + { + get { return _state; } + private set { SetValue(ref _state, value); } + } + + private bool _isBusy; + public bool IsBusy + { + get { return _isBusy; } + private set { SetValue(ref _isBusy, value); } + } + + private BaseDataViewModel _viewModel; + public BaseDataViewModel ViewModel + { + get { return _viewModel; } + set { SetValue(ref _viewModel, value); } + } + + private ICommand _deflateCommand; + public ICommand DeflateCommand + { + get { return _deflateCommand; } + private set { SetValue(ref _deflateCommand, value); } + } + + private ICommand _expandCommand; + public ICommand ExpandCommand + { + get { return _expandCommand; } + private set { SetValue(ref _expandCommand, value); } + } + + public VirtualizationViewModel(TKeyDataType id, IDataProvider, TKeyDataType> dataProvider) + { + _id = id; + _dataProvider = dataProvider ?? throw new ArgumentNullException(nameof(dataProvider), $"{nameof(dataProvider)} {Resources.IsRequired}"); + + DeflateCommand = new RelayCommand(Deflate, CanDeflate); + ExpandCommand = new RelayCommand(Expand, CanExpand); + } + + public void Expand() + { + if (ViewModel != null) + return; + + ViewModel = _dataProvider.Get(Id); + IsExtended = true; + } + + public bool CanExpand() + { + return false; // TODO add implementation + } + + public void Deflate() + { + ViewModel = null; // enables GC + IsExtended = false; + } + + public bool CanDeflate() + { + return false; // TODO add implementation + } + } +} diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModelState.cs b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModelState.cs new file mode 100644 index 0000000..3529da6 --- /dev/null +++ b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModelState.cs @@ -0,0 +1,14 @@ +using System; + +namespace Maple.Core +{ + [Flags] + public enum VirtualizationViewModelState + { + None = 0, + Expanded = 1 << 0, + Deflated = 1 << 1, + Expanding = 1 << 2, + Deflating = 1 << 3, + } +} diff --git a/src/Maple.Core/Services/Caching/ICachingService.cs b/src/Maple.Core/Services/Caching/ICachingService.cs new file mode 100644 index 0000000..2e51597 --- /dev/null +++ b/src/Maple.Core/Services/Caching/ICachingService.cs @@ -0,0 +1,11 @@ +namespace Maple.Core +{ + public interface ICachingService + { + bool Contains(TPrimaryKeyType key); + bool Add(TPrimaryKeyType key, TViewModel viewModel); + + void Clear(); + bool Remove(TPrimaryKeyType key); + } +} diff --git a/src/Maple.Core/Services/Caching/MemoryCacheService.cs b/src/Maple.Core/Services/Caching/MemoryCacheService.cs new file mode 100644 index 0000000..ce9120c --- /dev/null +++ b/src/Maple.Core/Services/Caching/MemoryCacheService.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Caching; +using Maple.Localization.Properties; + +namespace Maple.Core +{ + public abstract class MemoryCacheService : ICachingService + where TViewModel : class + { + private readonly HashSet _trackedEntries; + private readonly MemoryCache _cache; + private readonly CacheItemPolicy _policy; + private readonly IDataVirtualizationItemProvider _virtualizationProvider; + private readonly string _cacheKeyPart; + + private MemoryCacheService() + { + _cacheKeyPart = typeof(TViewModel).FullName; + _trackedEntries = new HashSet(); + _policy = new CacheItemPolicy() + { + SlidingExpiration = TimeSpan.FromSeconds(3), + Priority = CacheItemPriority.Default, + RemovedCallback = new CacheEntryRemovedCallback(CacheRemovedCallback) + }; + } + + protected MemoryCacheService(MemoryCache cache, IDataVirtualizationItemProvider virtualizationProvider) + : this() + { + _virtualizationProvider = virtualizationProvider ?? throw new ArgumentNullException(nameof(virtualizationProvider), $"{nameof(virtualizationProvider)} {Resources.IsRequired}"); + _cache = cache ?? throw new ArgumentNullException(nameof(cache), $"{nameof(cache)} {Resources.IsRequired}"); + } + + public bool Add(TPrimaryKeyType key, TViewModel viewModel) + { + if (viewModel == null) + throw new ArgumentNullException(nameof(viewModel), $"{nameof(viewModel)} {Resources.IsRequired}"); + + var result = _cache.Add(new CacheItem(_cacheKeyPart + key, viewModel), _policy); + + if (result) + _trackedEntries.Add(key); + + return result; + } + + public bool Contains(TPrimaryKeyType key) + { + return _cache.Contains(GetInternalKey(key)); + } + + public void Clear() + { + foreach (var entry in _trackedEntries) + Remove(entry); + + _trackedEntries.Clear(); + } + + public bool Remove(TPrimaryKeyType key) + { + var result = _cache.Remove(GetInternalKey(key)) is TViewModel; + + if (result) + _trackedEntries.Remove(key); + + return result; + } + + public abstract void CacheRemovedCallback(CacheEntryRemovedArguments arguments); + //{ + // _virtualizationProvider.DeflateItem(arguments.CacheItem.Value); + //} + + + private string GetInternalKey(TPrimaryKeyType key) + { + return _cacheKeyPart + key; + } + } +} diff --git a/src/Maple.Core/Services/Caching/SimpleInMemoryCacheService.cs b/src/Maple.Core/Services/Caching/SimpleInMemoryCacheService.cs new file mode 100644 index 0000000..455a61b --- /dev/null +++ b/src/Maple.Core/Services/Caching/SimpleInMemoryCacheService.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; + +namespace Maple.Core +{ + public class SimpleInMemoryCacheService : Dictionary, ICachingService + { + public bool Contains(TPrimaryKeyType key) + { + return ContainsKey(key); + } + + bool ICachingService.Add(TPrimaryKeyType key, TViewModel viewModel) + { + Add(key, viewModel); + + return true; + } + } +} diff --git a/src/Maple.Core/Services/Caching/WeakReferenceCache.cs b/src/Maple.Core/Services/Caching/WeakReferenceCache.cs new file mode 100644 index 0000000..2346e43 --- /dev/null +++ b/src/Maple.Core/Services/Caching/WeakReferenceCache.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Collections.Concurrent; + +namespace Maple.Core +{ + public class WeakReferenceCache : ICachingService + where TViewModel : class + { + private readonly ConcurrentDictionary> _references; + + public WeakReferenceCache() + { + _references = new ConcurrentDictionary>(); + } + + public bool Add(TPrimaryKeyType key, TViewModel viewModel) + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public bool Contains(TPrimaryKeyType key) + { + throw new NotImplementedException(); + } + + public bool Remove(TPrimaryKeyType key) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Maple.Core/Services/DetailLoggingService.cs b/src/Maple.Core/Services/Logging/DetailLoggingService.cs similarity index 93% rename from src/Maple.Core/Services/DetailLoggingService.cs rename to src/Maple.Core/Services/Logging/DetailLoggingService.cs index 2a40703..323923f 100644 --- a/src/Maple.Core/Services/DetailLoggingService.cs +++ b/src/Maple.Core/Services/Logging/DetailLoggingService.cs @@ -5,7 +5,7 @@ namespace Maple.Core { /// - /// Generates a Diagnostic report when exceptions are being thrown around + /// Facade that generates a diagnostic report when exceptions are being thrown around and forwards report and exceptions to the log /// public class DetailLoggingService : ILoggingService { diff --git a/src/Maple.Core/Services/LogNotifcationService.cs b/src/Maple.Core/Services/Logging/LogNotifcationService.cs similarity index 93% rename from src/Maple.Core/Services/LogNotifcationService.cs rename to src/Maple.Core/Services/Logging/LogNotifcationService.cs index e8e05c8..d586872 100644 --- a/src/Maple.Core/Services/LogNotifcationService.cs +++ b/src/Maple.Core/Services/Logging/LogNotifcationService.cs @@ -4,6 +4,9 @@ namespace Maple.Core { + /// + /// Facade to forward log messages to the UI + /// public class LoggingNotifcationService : ILoggingNotifcationService { private readonly ILoggingService _log; diff --git a/src/Maple.Core/Services/LoggingService.cs b/src/Maple.Core/Services/Logging/LoggingService.cs similarity index 99% rename from src/Maple.Core/Services/LoggingService.cs rename to src/Maple.Core/Services/Logging/LoggingService.cs index 32d04b0..88c8670 100644 --- a/src/Maple.Core/Services/LoggingService.cs +++ b/src/Maple.Core/Services/Logging/LoggingService.cs @@ -5,7 +5,7 @@ namespace Maple.Core { /// - /// + /// actual log /// /// public class LoggingService : ILoggingService diff --git a/src/Maple.Data/DB/CreateSeedDatabaseIfNotExists.cs b/src/Maple.Data/DB/CreateSeedDatabaseIfNotExists.cs index e19a43f..a514349 100644 --- a/src/Maple.Data/DB/CreateSeedDatabaseIfNotExists.cs +++ b/src/Maple.Data/DB/CreateSeedDatabaseIfNotExists.cs @@ -187,99 +187,99 @@ private void SeedMediaPlayers(TContext context) }); } - private void SeedOptions(TContext context) - { - if (context.Options.Find(1) == null) - context.Options - .Add(new OptionModel - { - Id = 1, - Key = "SelectedPlaylist", - Sequence = 0, - Type = (int)OptionType.Playlist, - Value = "1", - CreatedBy = "SYSTEM", - UpdatedBy = "SYSTEM", - CreatedOn = DateTime.UtcNow, - UpdatedOn = DateTime.UtcNow, - }); + //private void SeedOptions(TContext context) + //{ + // if (context.Options.Find(1) == null) + // context.Options + // .Add(new OptionModel + // { + // Id = 1, + // Key = "SelectedPlaylist", + // Sequence = 0, + // Type = (int)OptionType.Playlist, + // Value = "1", + // CreatedBy = "SYSTEM", + // UpdatedBy = "SYSTEM", + // CreatedOn = DateTime.UtcNow, + // UpdatedOn = DateTime.UtcNow, + // }); - if (context.Options.Find(2) == null) - context.Options - .Add(new OptionModel - { - Id = 2, - Key = "SelectedMediaItem", - Sequence = 10, - Type = (int)OptionType.MediaItem, - Value = "", - CreatedBy = "SYSTEM", - UpdatedBy = "SYSTEM", - CreatedOn = DateTime.UtcNow, - UpdatedOn = DateTime.UtcNow, - }); + // if (context.Options.Find(2) == null) + // context.Options + // .Add(new OptionModel + // { + // Id = 2, + // Key = "SelectedMediaItem", + // Sequence = 10, + // Type = (int)OptionType.MediaItem, + // Value = "", + // CreatedBy = "SYSTEM", + // UpdatedBy = "SYSTEM", + // CreatedOn = DateTime.UtcNow, + // UpdatedOn = DateTime.UtcNow, + // }); - if (context.Options.Find(3) == null) - context.Options - .Add(new OptionModel - { - Id = 3, - Key = "SelectedMediaPlayer", - Sequence = 20, - Type = (int)OptionType.MediaPlayer, - Value = "1", - CreatedBy = "SYSTEM", - UpdatedBy = "SYSTEM", - CreatedOn = DateTime.UtcNow, - UpdatedOn = DateTime.UtcNow, - }); + // if (context.Options.Find(3) == null) + // context.Options + // .Add(new OptionModel + // { + // Id = 3, + // Key = "SelectedMediaPlayer", + // Sequence = 20, + // Type = (int)OptionType.MediaPlayer, + // Value = "1", + // CreatedBy = "SYSTEM", + // UpdatedBy = "SYSTEM", + // CreatedOn = DateTime.UtcNow, + // UpdatedOn = DateTime.UtcNow, + // }); - // 4 + // // 4 - if (context.Options.Find(5) == null) - context.Options - .Add(new OptionModel - { - Id = 5, - Key = "SelectedPrimary", - Sequence = 40, - Type = (int)OptionType.ColorProfile, - Value = "", - CreatedBy = "SYSTEM", - UpdatedBy = "SYSTEM", - CreatedOn = DateTime.UtcNow, - UpdatedOn = DateTime.UtcNow, - }); + // if (context.Options.Find(5) == null) + // context.Options + // .Add(new OptionModel + // { + // Id = 5, + // Key = "SelectedPrimary", + // Sequence = 40, + // Type = (int)OptionType.ColorProfile, + // Value = "", + // CreatedBy = "SYSTEM", + // UpdatedBy = "SYSTEM", + // CreatedOn = DateTime.UtcNow, + // UpdatedOn = DateTime.UtcNow, + // }); - if (context.Options.Find(6) == null) - context.Options - .Add(new OptionModel - { - Id = 6, - Key = "SelectedAccent", - Sequence = 50, - Type = (int)OptionType.ColorProfile, - Value = "", - CreatedBy = "SYSTEM", - UpdatedBy = "SYSTEM", - CreatedOn = DateTime.UtcNow, - UpdatedOn = DateTime.UtcNow, - }); + // if (context.Options.Find(6) == null) + // context.Options + // .Add(new OptionModel + // { + // Id = 6, + // Key = "SelectedAccent", + // Sequence = 50, + // Type = (int)OptionType.ColorProfile, + // Value = "", + // CreatedBy = "SYSTEM", + // UpdatedBy = "SYSTEM", + // CreatedOn = DateTime.UtcNow, + // UpdatedOn = DateTime.UtcNow, + // }); - if (context.Options.Find(7) == null) - context.Options - .Add(new OptionModel - { - Id = 7, - Key = "SelectedScene", - Sequence = 60, - Type = (int)OptionType.Scene, - Value = "", - CreatedBy = "SYSTEM", - UpdatedBy = "SYSTEM", - CreatedOn = DateTime.UtcNow, - UpdatedOn = DateTime.UtcNow, - }); - } + // if (context.Options.Find(7) == null) + // context.Options + // .Add(new OptionModel + // { + // Id = 7, + // Key = "SelectedScene", + // Sequence = 60, + // Type = (int)OptionType.Scene, + // Value = "", + // CreatedBy = "SYSTEM", + // UpdatedBy = "SYSTEM", + // CreatedOn = DateTime.UtcNow, + // UpdatedOn = DateTime.UtcNow, + // }); + //} } } diff --git a/src/Maple.Data/DB/PlaylistContext.cs b/src/Maple.Data/DB/PlaylistContext.cs index c5425f2..1801c1b 100644 --- a/src/Maple.Data/DB/PlaylistContext.cs +++ b/src/Maple.Data/DB/PlaylistContext.cs @@ -8,8 +8,6 @@ public class PlaylistContext : DbContext public DbSet Playlists { get; set; } public DbSet MediaItems { get; set; } public DbSet Mediaplayers { get; set; } - public DbSet Options { get; set; } - public DbSet Data { get; set; } public PlaylistContext() : base("Main") diff --git a/src/Maple.Data/Repository/Base/IMediaItemRepository.cs b/src/Maple.Data/Repository/Base/IMediaItemRepository.cs index fa4f713..9edca02 100644 --- a/src/Maple.Data/Repository/Base/IMediaItemRepository.cs +++ b/src/Maple.Data/Repository/Base/IMediaItemRepository.cs @@ -3,7 +3,7 @@ namespace Maple.Data { - public interface IMediaItemRepository : IMapleRepository + public interface IMediaItemRepository : IMapleRepository { Task GetMediaItemByPlaylistIdAsync(int id); } diff --git a/src/Maple.Data/Repository/Base/IMediaPlayerRepository.cs b/src/Maple.Data/Repository/Base/IMediaPlayerRepository.cs index bdc5e88..c703daa 100644 --- a/src/Maple.Data/Repository/Base/IMediaPlayerRepository.cs +++ b/src/Maple.Data/Repository/Base/IMediaPlayerRepository.cs @@ -4,7 +4,7 @@ namespace Maple.Data { - public interface IMediaPlayerRepository : IMapleRepository + public interface IMediaPlayerRepository : IMapleRepository { Task GetMainMediaPlayerAsync(); Task> GetOptionalMediaPlayersAsync(); diff --git a/src/Maple.Data/Repository/Base/IPlaylistRepository.cs b/src/Maple.Data/Repository/Base/IPlaylistRepository.cs index 0b5d03b..8d7606b 100644 --- a/src/Maple.Data/Repository/Base/IPlaylistRepository.cs +++ b/src/Maple.Data/Repository/Base/IPlaylistRepository.cs @@ -2,7 +2,7 @@ namespace Maple.Data { - public interface IPlaylistRepository : IMapleRepository + public interface IPlaylistRepository : IMapleRepository { } } \ No newline at end of file diff --git a/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs b/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs index a17b0ed..20c7f34 100644 --- a/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs +++ b/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs @@ -8,18 +8,42 @@ namespace Maple.Data { - public abstract class MaplePlaylistRepository : IMapleRepository - where T : class, IBaseObject + public abstract class MaplePlaylistRepository : IMapleRepository + where TModel : class, IBaseObject { - public void Save(T item) + public async Task Save(TModel item) { using (var context = new PlaylistContext()) - SaveInternal(item, context); + await SaveInternal(item, context).ConfigureAwait(false); } - protected abstract DbSet GetEntities(PlaylistContext context); + public async Task GetByIdAsync(TKeyDataType Id) + { + using (var context = new PlaylistContext()) + return await GetByIdInternalAsync(Id, context).ConfigureAwait(false); + } + + public async Task> GetAsync() + { + using (var context = new PlaylistContext()) + return await GetInternalAsync(context).ConfigureAwait(false); + } + + public async Task> GetKeysAsync() + { + using (var context = new PlaylistContext()) + return await GetEntities(context).Select(p => p.Id).ToListAsync().ConfigureAwait(false); + } + + public async Task GetEntryCountAsync() + { + using (var context = new PlaylistContext()) + return await GetEntities(context).CountAsync().ConfigureAwait(false); + } - protected virtual void SaveInternal(T item, PlaylistContext context) + protected abstract DbSet GetEntities(PlaylistContext context); + + protected virtual async Task SaveInternal(TModel item, PlaylistContext context) { if (item.IsNew) Create(item, context); @@ -31,28 +55,28 @@ protected virtual void SaveInternal(T item, PlaylistContext context) Delete(item, context); } else - Update(item, context); + await Update(item, context).ConfigureAwait(false); } - context.SaveChanges(); + await context.SaveChangesAsync().ConfigureAwait(false); } - protected virtual void Delete(T item, PlaylistContext context) + protected virtual void Delete(TModel item, PlaylistContext context) { - context.Set().Remove(item); + context.Set().Remove(item); } - protected virtual void Create(T item, PlaylistContext context) + protected virtual void Create(TModel item, PlaylistContext context) { item.CreatedBy = System.Security.Principal.WindowsIdentity.GetCurrent().User.Value; item.CreatedOn = DateTime.UtcNow; - context.Set().Add(item); + context.Set().Add(item); } - protected virtual void Update(T item, PlaylistContext context) + protected virtual async Task Update(TModel item, PlaylistContext context) { - var entity = GetEntities(context).Find(item.Id); + var entity = await GetEntities(context).FindAsync(item.Id).ConfigureAwait(false); if (entity == null) return; @@ -64,32 +88,15 @@ protected virtual void Update(T item, PlaylistContext context) context.Entry(entity).CurrentValues.SetValues(item); } - public Task GetByIdAsync(int Id) - { - return Task.Run(() => - { - using (var context = new PlaylistContext()) - return GetByIdInternalAsync(Id, context); - }); - } - - protected virtual T GetByIdInternalAsync(int id, PlaylistContext context) - { - return GetEntities(context).FirstOrDefault(p => p.Id == id); - } - - public Task> GetAsync() + protected virtual Task GetByIdInternalAsync(TKeyDataType id, PlaylistContext context) { - return Task.Run(() => - { - using (var context = new PlaylistContext()) - return GetInternalAsync(context); - }); + return GetEntities(context).FirstOrDefaultAsync(p => EqualityComparer.Default.Equals(p.Id, id)); } - protected virtual IReadOnlyCollection GetInternalAsync(PlaylistContext context) + // override if you need to include foreignkeys + protected virtual Task> GetInternalAsync(PlaylistContext context) { - return GetEntities(context).ToList(); + return GetEntities(context).ToListAsync(); } } } \ No newline at end of file diff --git a/src/Maple.Data/Repository/MediaItemRepository.cs b/src/Maple.Data/Repository/MediaItemRepository.cs index 1bf662c..d36e73c 100644 --- a/src/Maple.Data/Repository/MediaItemRepository.cs +++ b/src/Maple.Data/Repository/MediaItemRepository.cs @@ -1,19 +1,15 @@ using System.Data.Entity; -using System.Linq; using System.Threading.Tasks; using Maple.Domain; namespace Maple.Data { - public class MediaItemRepository : MaplePlaylistRepository, IMediaItemRepository + public class MediaItemRepository : MaplePlaylistRepository, IMediaItemRepository { - public Task GetMediaItemByPlaylistIdAsync(int id) + public async Task GetMediaItemByPlaylistIdAsync(int id) { - return Task.Run(() => - { - using (var context = new PlaylistContext()) - return GetMediaItemByPlaylistIdInternalAsync(id, context); - }); + using (var context = new PlaylistContext()) + return await GetMediaItemByPlaylistIdInternalAsync(id, context).ConfigureAwait(false); } protected override DbSet GetEntities(PlaylistContext context) @@ -21,9 +17,9 @@ protected override DbSet GetEntities(PlaylistContext context) return context.MediaItems; } - private MediaItemModel GetMediaItemByPlaylistIdInternalAsync(int id, PlaylistContext context) + private async Task GetMediaItemByPlaylistIdInternalAsync(int id, PlaylistContext context) { - return context.MediaItems.FirstOrDefault(p => p.Playlist.Id == id); + return await GetEntities(context).FirstOrDefaultAsync(p => p.Playlist.Id == id).ConfigureAwait(false); } } } diff --git a/src/Maple.Data/Repository/MediaPlayerRepository.cs b/src/Maple.Data/Repository/MediaPlayerRepository.cs index 70ebbee..3e726b2 100644 --- a/src/Maple.Data/Repository/MediaPlayerRepository.cs +++ b/src/Maple.Data/Repository/MediaPlayerRepository.cs @@ -6,43 +6,39 @@ namespace Maple.Data { - public class MediaPlayerRepository : MaplePlaylistRepository, IMediaPlayerRepository + public class MediaPlayerRepository : MaplePlaylistRepository, IMediaPlayerRepository { - public Task GetMainMediaPlayerAsync() + public async Task GetMainMediaPlayerAsync() { - return Task.Run(() => - { - using (var context = new PlaylistContext()) - return GetMainMediaPlayerInternal(context); - }); + using (var context = new PlaylistContext()) + return await GetMainMediaPlayerInternal(context).ConfigureAwait(false); } - private MediaPlayerModel GetMainMediaPlayerInternal(PlaylistContext context) + private async Task GetMainMediaPlayerInternal(PlaylistContext context) { - return GetEntities(context).Include(p => p.Playlist) + return await GetEntities(context).Include(p => p.Playlist) .Include(p => p.Playlist.MediaItems) - .FirstOrDefault(p => p.IsPrimary); + .FirstOrDefaultAsync(p => p.IsPrimary) + .ConfigureAwait(false); } - public Task> GetOptionalMediaPlayersAsync() + public async Task> GetOptionalMediaPlayersAsync() { - return Task.Run(() => - { - using (var context = new PlaylistContext()) - return GetOptionalMediaPlayersInternal(context); - }); + using (var context = new PlaylistContext()) + return await GetOptionalMediaPlayersInternal(context).ConfigureAwait(false); } - private IReadOnlyCollection GetOptionalMediaPlayersInternal(PlaylistContext context) + private async Task> GetOptionalMediaPlayersInternal(PlaylistContext context) { - return GetEntities(context).Include(p => p.Playlist) + return await GetEntities(context).Include(p => p.Playlist) .Where(p => !p.IsPrimary) - .ToList(); + .ToListAsync() + .ConfigureAwait(false); } - protected override IReadOnlyCollection GetInternalAsync(PlaylistContext context) + protected override async Task> GetInternalAsync(PlaylistContext context) { - return GetEntities(context).Include(p => p.Playlist).ToList(); + return await GetEntities(context).Include(p => p.Playlist).ToListAsync().ConfigureAwait(false); } protected override DbSet GetEntities(PlaylistContext context) diff --git a/src/Maple.Data/Repository/PlaylistRepository.cs b/src/Maple.Data/Repository/PlaylistRepository.cs index bfad325..4dc87b6 100644 --- a/src/Maple.Data/Repository/PlaylistRepository.cs +++ b/src/Maple.Data/Repository/PlaylistRepository.cs @@ -1,20 +1,20 @@ using System.Collections.Generic; using System.Data.Entity; -using System.Linq; +using System.Threading.Tasks; using Maple.Domain; namespace Maple.Data { - public class PlaylistRepository : MaplePlaylistRepository, IPlaylistRepository + public class PlaylistRepository : MaplePlaylistRepository, IPlaylistRepository { protected override DbSet GetEntities(PlaylistContext context) { return context.Playlists; } - protected override IReadOnlyCollection GetInternalAsync(PlaylistContext context) + protected override async Task> GetInternalAsync(PlaylistContext context) { - return GetEntities(context).Include(p => p.MediaItems).ToList(); + return await GetEntities(context).Include(p => p.MediaItems).ToListAsync().ConfigureAwait(false); } } } diff --git a/src/Maple.Domain/Interfaces/IBaseObject.cs b/src/Maple.Domain/Interfaces/IBaseObject.cs index c1740cb..96459b6 100644 --- a/src/Maple.Domain/Interfaces/IBaseObject.cs +++ b/src/Maple.Domain/Interfaces/IBaseObject.cs @@ -2,11 +2,11 @@ namespace Maple.Domain { - public interface IBaseObject + public interface IBaseObject { string CreatedBy { get; set; } DateTime CreatedOn { get; set; } - int Id { get; set; } + TKeyDataType Id { get; set; } bool IsDeleted { get; set; } bool IsNew { get; } byte[] RowVersion { get; set; } diff --git a/src/Maple.Domain/Interfaces/IMapleRepository.cs b/src/Maple.Domain/Interfaces/IMapleRepository.cs index e5a4434..3cce265 100644 --- a/src/Maple.Domain/Interfaces/IMapleRepository.cs +++ b/src/Maple.Domain/Interfaces/IMapleRepository.cs @@ -3,11 +3,15 @@ namespace Maple.Domain { - public interface IMapleRepository - where T : class, IBaseObject + public interface IMapleRepository + where TModel : class, IBaseObject { - Task> GetAsync(); - Task GetByIdAsync(int Id); - void Save(T item); + Task> GetAsync(); + Task GetByIdAsync(TKeyDataType Id); + + Task> GetKeysAsync(); + Task GetEntryCountAsync(); + + Task Save(TModel item); } } \ No newline at end of file diff --git a/src/Maple.Domain/Maple.Domain.csproj b/src/Maple.Domain/Maple.Domain.csproj index 2050693..0c1d2c2 100644 --- a/src/Maple.Domain/Maple.Domain.csproj +++ b/src/Maple.Domain/Maple.Domain.csproj @@ -72,9 +72,7 @@ - - diff --git a/src/Maple.Domain/Models/Base/BaseObject.cs b/src/Maple.Domain/Models/Base/BaseObject.cs index 84b225c..3ab65c9 100644 --- a/src/Maple.Domain/Models/Base/BaseObject.cs +++ b/src/Maple.Domain/Models/Base/BaseObject.cs @@ -1,14 +1,15 @@ using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Maple.Domain { - public abstract class BaseObject : IBaseObject + public abstract class BaseObject : IBaseObject { [Key] [Column(Order = 1)] - public int Id { get; set; } + public TKeyDataType Id { get; set; } [Column(Order = 2)] public int Sequence { get; set; } @@ -25,6 +26,6 @@ public abstract class BaseObject : IBaseObject public bool IsDeleted { get; set; } [NotMapped] - public bool IsNew => Id == 0; + public bool IsNew => EqualityComparer.Default.Equals(Id, default(TKeyDataType)); } } diff --git a/src/Maple.Domain/Models/MediaItemModel.cs b/src/Maple.Domain/Models/MediaItemModel.cs index 92d84e0..b34e99e 100644 --- a/src/Maple.Domain/Models/MediaItemModel.cs +++ b/src/Maple.Domain/Models/MediaItemModel.cs @@ -5,14 +5,12 @@ namespace Maple.Domain { [DebuggerDisplay("{Title}, {Sequence}")] - public class MediaItemModel : BaseObject + public class MediaItemModel : BaseObject { public int PlaylistId { get; set; } [ForeignKey(nameof(PlaylistId))] public PlaylistModel Playlist { get; set; } - public RawModel Raw { get; set; } - /// /// Ticks /// diff --git a/src/Maple.Domain/Models/MediaPlayerModel.cs b/src/Maple.Domain/Models/MediaPlayerModel.cs index 4775b57..418f223 100644 --- a/src/Maple.Domain/Models/MediaPlayerModel.cs +++ b/src/Maple.Domain/Models/MediaPlayerModel.cs @@ -5,7 +5,7 @@ namespace Maple.Domain { [DebuggerDisplay("{Name}, {DeviceName}, {Sequence}")] - public class MediaPlayerModel : BaseObject + public class MediaPlayerModel : BaseObject { public int PlaylistId { get; set; } [ForeignKey(nameof(PlaylistId))] diff --git a/src/Maple.Domain/Models/OptionModel.cs b/src/Maple.Domain/Models/OptionModel.cs deleted file mode 100644 index ec27dc4..0000000 --- a/src/Maple.Domain/Models/OptionModel.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using System.Diagnostics; - -namespace Maple.Domain -{ - [DebuggerDisplay("{Key}, {Value}, {Type}")] - public class OptionModel : BaseObject - { - public string Value { get; set; } - public int Type { get; set; } - - - [Required] - public string Key { get; set; } - } -} diff --git a/src/Maple.Domain/Models/PlaylistModel.cs b/src/Maple.Domain/Models/PlaylistModel.cs index 8d96ad8..d03b50e 100644 --- a/src/Maple.Domain/Models/PlaylistModel.cs +++ b/src/Maple.Domain/Models/PlaylistModel.cs @@ -7,7 +7,7 @@ namespace Maple.Domain // tutorial http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx [DebuggerDisplay("{Title}, {SelectedItem}, {Sequence}")] - public class PlaylistModel : BaseObject + public class PlaylistModel : BaseObject { private ICollection _mediaItems; public virtual ICollection MediaItems diff --git a/src/Maple.Domain/Models/RawModel.cs b/src/Maple.Domain/Models/RawModel.cs deleted file mode 100644 index 182e8cf..0000000 --- a/src/Maple.Domain/Models/RawModel.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Maple.Domain -{ - public class RawModel : BaseObject - { - public byte[] Data { get; set; } - } -} diff --git a/src/Maple/Interfaces/IBaseMapper.cs b/src/Maple/Interfaces/IBaseMapper.cs index 6288c78..ed5d02b 100644 --- a/src/Maple/Interfaces/IBaseMapper.cs +++ b/src/Maple/Interfaces/IBaseMapper.cs @@ -3,9 +3,9 @@ namespace Maple { - public interface IBaseMapper - where TVieModel : BaseDataViewModel - where TDataModel : class, IBaseObject + public interface IBaseMapper + where TVieModel : BaseDataViewModel + where TDataModel : class, IBaseObject { TVieModel Get(TDataModel model); diff --git a/src/Maple/Interfaces/IMediaItemMapper.cs b/src/Maple/Interfaces/IMediaItemMapper.cs index f987723..b8e453f 100644 --- a/src/Maple/Interfaces/IMediaItemMapper.cs +++ b/src/Maple/Interfaces/IMediaItemMapper.cs @@ -2,7 +2,7 @@ namespace Maple { - public interface IMediaItemMapper : IBaseMapper + public interface IMediaItemMapper : IBaseMapper { MediaItem GetNewMediaItem(int sequence, Playlist playlist); MediaItemModel GetDataNewMediaItem(PlaylistModel playlist); diff --git a/src/Maple/Interfaces/IMediaPlayerMapper.cs b/src/Maple/Interfaces/IMediaPlayerMapper.cs index ed7f9cb..7097556 100644 --- a/src/Maple/Interfaces/IMediaPlayerMapper.cs +++ b/src/Maple/Interfaces/IMediaPlayerMapper.cs @@ -2,7 +2,7 @@ namespace Maple { - public interface IMediaPlayerMapper : IBaseMapper + public interface IMediaPlayerMapper : IBaseMapper { MainMediaPlayer GetMain(MediaPlayerModel player, Playlist playlist); diff --git a/src/Maple/Interfaces/IPlaylistMapper.cs b/src/Maple/Interfaces/IPlaylistMapper.cs index 014b807..bdcf15e 100644 --- a/src/Maple/Interfaces/IPlaylistMapper.cs +++ b/src/Maple/Interfaces/IPlaylistMapper.cs @@ -2,7 +2,7 @@ namespace Maple { - public interface IPlaylistMapper : IBaseMapper + public interface IPlaylistMapper : IBaseMapper { Playlist GetNewPlaylist(); } diff --git a/src/Maple/ViewModels/MediaItems/MediaItem.cs b/src/Maple/ViewModels/MediaItems/MediaItem.cs index 5639dfb..8354ba2 100644 --- a/src/Maple/ViewModels/MediaItems/MediaItem.cs +++ b/src/Maple/ViewModels/MediaItems/MediaItem.cs @@ -12,7 +12,7 @@ namespace Maple /// /// [DebuggerDisplay("{Title}, {Sequence} {Location}")] - public class MediaItem : ValidableBaseDataViewModel, IMediaItem + public class MediaItem : ValidableBaseDataViewModel, IMediaItem { public bool IsNew => Model.IsNew; public bool IsDeleted => Model.IsDeleted; diff --git a/src/Maple/ViewModels/MediaItems/MediaItems.cs b/src/Maple/ViewModels/MediaItems/MediaItems.cs index ce97881..bbef663 100644 --- a/src/Maple/ViewModels/MediaItems/MediaItems.cs +++ b/src/Maple/ViewModels/MediaItems/MediaItems.cs @@ -7,7 +7,7 @@ namespace Maple { - public class MediaItems : BaseDataListViewModel, IMediaItemsViewModel + public class MediaItems : BaseDataListViewModel, IMediaItemsViewModel { private readonly Func _repositoryFactory; private readonly IMediaItemMapper _mediaItemMapper; diff --git a/src/Maple/ViewModels/MediaPlayer/MediaPlayer.cs b/src/Maple/ViewModels/MediaPlayer/MediaPlayer.cs index de531f3..8a79a5a 100644 --- a/src/Maple/ViewModels/MediaPlayer/MediaPlayer.cs +++ b/src/Maple/ViewModels/MediaPlayer/MediaPlayer.cs @@ -11,7 +11,7 @@ namespace Maple { [DebuggerDisplay("{Name}, {Sequence}")] - public class MediaPlayer : ValidableBaseDataViewModel, IDisposable, IChangeState, ISequence + public class MediaPlayer : ValidableBaseDataViewModel, IDisposable, IChangeState, ISequence { protected readonly ILocalizationService _manager; diff --git a/src/Maple/ViewModels/MediaPlayer/MediaPlayers.cs b/src/Maple/ViewModels/MediaPlayer/MediaPlayers.cs index f482a5f..1a735fe 100644 --- a/src/Maple/ViewModels/MediaPlayer/MediaPlayers.cs +++ b/src/Maple/ViewModels/MediaPlayer/MediaPlayers.cs @@ -7,7 +7,7 @@ namespace Maple { - public class MediaPlayers : BaseDataListViewModel, IMediaPlayersViewModel + public class MediaPlayers : BaseDataListViewModel, IMediaPlayersViewModel { private readonly Func _playerFactory; private readonly AudioDevices _devices; diff --git a/src/Maple/ViewModels/Playlists/Playlist.cs b/src/Maple/ViewModels/Playlists/Playlist.cs index baa7bc1..6b55db7 100644 --- a/src/Maple/ViewModels/Playlists/Playlist.cs +++ b/src/Maple/ViewModels/Playlists/Playlist.cs @@ -16,7 +16,7 @@ namespace Maple { [DebuggerDisplay("{Title}, {Sequence}")] - public class Playlist : ValidableBaseDataViewModel, IIsSelected, ISequence, IIdentifier, IChangeState + public class Playlist : ValidableBaseDataViewModel, IIsSelected, ISequence, IIdentifier, IChangeState { private readonly IMediaItemMapper _mediaItemMapper; private readonly ISequenceService _sequenceProvider; diff --git a/src/Maple/ViewModels/Playlists/Playlists.cs b/src/Maple/ViewModels/Playlists/Playlists.cs index 5f425ea..6547665 100644 --- a/src/Maple/ViewModels/Playlists/Playlists.cs +++ b/src/Maple/ViewModels/Playlists/Playlists.cs @@ -7,7 +7,7 @@ namespace Maple { - public class Playlists : BaseDataListViewModel, ISaveableViewModel, IPlaylistsViewModel + public class Playlists : BaseDataListViewModel, ISaveableViewModel, IPlaylistsViewModel { private readonly Func _repositoryFactory; private readonly IPlaylistMapper _playlistMapper; From feec8257eb1f82d5c493b6876f09524b5e1253dd Mon Sep 17 00:00:00 2001 From: Insire Date: Mon, 8 Jan 2018 18:51:50 +0100 Subject: [PATCH 02/16] added async workflow from UI to DAL for saving --- .../Interfaces/ILoadableViewModel.cs | 15 ++-- .../Interfaces/ILocalizationService.cs | 2 +- .../Interfaces/ISaveableViewModel.cs | 6 +- src/Maple.Core/Maple.Core.csproj | 6 +- .../ViewModels/BaseDataListViewModel.cs | 37 +++------ .../ViewModels/BaseListViewModel.cs | 55 ++----------- .../ValidableBaseDataListViewModel.cs | 16 ++++ ...emProvider.cs => IVirtualizedViewModel.cs} | 2 +- .../DataVirtualizationCollectionView.cs | 10 +-- .../VirtualizationListViewModel.cs | 78 +++++++++++++++++++ .../Services/Caching/MemoryCacheService.cs | 4 +- .../Localization/LocalizationService.cs | 14 ++-- .../Base/MaplePlaylistRepository.cs | 2 +- .../Interfaces/IMapleRepository.cs | 2 +- src/Maple.Domain/Interfaces/IRefreshable.cs | 4 +- .../ViewModels/Playlists/PlaylistTests.cs | 2 - .../ViewModels/Playlists/PlaylistsTests.cs | 4 +- src/Maple/App.xaml.cs | 16 ++-- src/Maple/Interfaces/IMediaRepository.cs | 13 ++-- src/Maple/Services/MediaRepository.cs | 46 +++++------ src/Maple/Utils/DependencyInjectionFactory.cs | 11 +-- .../Utils/Validation/PlaylistValidator.cs | 5 -- .../Interfaces/IMediaItemsViewModel.cs | 4 +- src/Maple/ViewModels/MediaItems/MediaItem.cs | 32 -------- src/Maple/ViewModels/MediaItems/MediaItems.cs | 21 ++--- .../ViewModels/MediaPlayer/AudioDevice.cs | 2 - .../ViewModels/MediaPlayer/MediaPlayer.cs | 33 -------- .../ViewModels/MediaPlayer/MediaPlayers.cs | 21 ++--- src/Maple/ViewModels/Playlists/Playlist.cs | 20 ----- src/Maple/ViewModels/Playlists/Playlists.cs | 21 ++--- src/Maple/ViewModels/Settings/Cultures.cs | 26 +++++-- .../ViewModels/Settings/UIColorsViewModel.cs | 17 ++-- 32 files changed, 241 insertions(+), 306 deletions(-) create mode 100644 src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs rename src/Maple.Core/Observables/Virtualization/Base/{IDataVirtualizationItemProvider.cs => IVirtualizedViewModel.cs} (75%) create mode 100644 src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs diff --git a/src/Maple.Core/Interfaces/ILoadableViewModel.cs b/src/Maple.Core/Interfaces/ILoadableViewModel.cs index e00dcb7..205f904 100644 --- a/src/Maple.Core/Interfaces/ILoadableViewModel.cs +++ b/src/Maple.Core/Interfaces/ILoadableViewModel.cs @@ -1,13 +1,8 @@ -using System.Windows.Input; -using Maple.Domain; +using System.Threading.Tasks; namespace Maple.Core { - /// - /// - /// - /// - public interface ILoadableViewModel : IRefreshable + public interface ILoadableViewModel { /// /// Gets a value indicating whether this instance is loaded. @@ -17,7 +12,9 @@ public interface ILoadableViewModel : IRefreshable /// bool IsLoaded { get; } - ICommand LoadCommand { get; } - ICommand RefreshCommand { get; } + IAsyncCommand LoadCommand { get; } + IAsyncCommand RefreshCommand { get; } + + Task LoadAsync(); } } diff --git a/src/Maple.Core/Interfaces/ILocalizationService.cs b/src/Maple.Core/Interfaces/ILocalizationService.cs index 987ad62..d82a308 100644 --- a/src/Maple.Core/Interfaces/ILocalizationService.cs +++ b/src/Maple.Core/Interfaces/ILocalizationService.cs @@ -10,7 +10,7 @@ namespace Maple.Core /// /// /// - public interface ILocalizationService : INotifyPropertyChanged, IRefreshable + public interface ILocalizationService : INotifyPropertyChanged, ILoadAndSaveProvider { /// /// Gets or sets the current language. diff --git a/src/Maple.Core/Interfaces/ISaveableViewModel.cs b/src/Maple.Core/Interfaces/ISaveableViewModel.cs index 219cefc..30e21ab 100644 --- a/src/Maple.Core/Interfaces/ISaveableViewModel.cs +++ b/src/Maple.Core/Interfaces/ISaveableViewModel.cs @@ -1,9 +1,11 @@ -using System.Windows.Input; +using System.Threading.Tasks; namespace Maple.Core { public interface ISaveableViewModel { - ICommand SaveCommand { get; } + IAsyncCommand SaveCommand { get; } + + Task SaveAsync(); } } diff --git a/src/Maple.Core/Maple.Core.csproj b/src/Maple.Core/Maple.Core.csproj index c669c5b..07a3cca 100644 --- a/src/Maple.Core/Maple.Core.csproj +++ b/src/Maple.Core/Maple.Core.csproj @@ -126,14 +126,16 @@ + - - + + + diff --git a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs index 0b71157..dff50b5 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using System.Windows.Input; using Maple.Domain; using Maple.Localization.Properties; @@ -15,7 +14,7 @@ namespace Maple.Core /// a wrapper class implementing /// a DTO implementing /// - public abstract class BaseDataListViewModel : BaseListViewModel, ILoadableViewModel + public abstract class BaseDataListViewModel : BaseListViewModel, ILoadableViewModel, ISaveableViewModel where TViewModel : BaseDataViewModel, ISequence where TModel : class, IBaseObject { @@ -23,27 +22,14 @@ public abstract class BaseDataListViewModel : protected readonly ILocalizationService _translationService; protected readonly ILoggingService _log; - /// - /// Gets the load command. - /// - /// - /// The load command. - /// - public ICommand LoadCommand => AsyncCommand.Create(LoadAsync, () => !IsLoaded); - /// - /// Gets the refresh command. - /// - /// - /// The refresh command. - /// - public ICommand RefreshCommand => AsyncCommand.Create(LoadAsync); - /// - /// Gets the save command. - /// - /// - /// The save command. - /// - public ICommand SaveCommand => new RelayCommand(Save); + public abstract bool IsLoaded { get; protected set; } + + public abstract IAsyncCommand SaveCommand { get; } + public abstract IAsyncCommand LoadCommand { get; } + public abstract IAsyncCommand RefreshCommand { get; } + + public abstract Task LoadAsync(); + public abstract Task SaveAsync(); protected BaseDataListViewModel(ViewModelServiceContainer container) : base(container.Messenger) @@ -53,9 +39,6 @@ protected BaseDataListViewModel(ViewModelServiceContainer container) _sequenceProvider = container.SequenceService; } - public abstract Task LoadAsync(); - public abstract void Save(); - /// /// Removes the specified item. /// @@ -141,5 +124,7 @@ public override void AddRange(IEnumerable items) SelectedItem = Items.First(); } } + + } } diff --git a/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs index f6f54aa..45b97e7 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs @@ -1,11 +1,9 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Linq; -using System.Windows.Data; using System.Windows.Input; using Maple.Domain; @@ -19,13 +17,6 @@ namespace Maple.Core public abstract class BaseListViewModel : ViewModel where TViewModel : INotifyPropertyChanged { - protected readonly object _itemsLock; - - /// - /// Indicates whether the LoadCommand/ the Load Method has been executed yet - /// - public bool IsLoaded { get; protected set; } - private TViewModel _selectedItem; public virtual TViewModel SelectedItem { @@ -51,7 +42,7 @@ public virtual TViewModel SelectedItem public IReadOnlyCollection Items { get { return (IReadOnlyCollection)_items; } - private set { SetValue(ref _items, (IRangeObservableCollection)value); } + protected set { SetValue(ref _items, (IRangeObservableCollection)value); } } private ICollectionView _view; @@ -64,10 +55,9 @@ public IReadOnlyCollection Items public ICollectionView View { get { return _view; } - private set { SetValue(ref _view, value); } + protected set { SetValue(ref _view, value); } } - public int Count => Items?.Count ?? 0; /// /// Gets the at the specified index. /// @@ -88,51 +78,16 @@ public TViewModel this[int index] protected BaseListViewModel(IMessenger messenger) : base(messenger) - { - _itemsLock = new object(); - - - Items = new RangeObservableCollection(); - _items.CollectionChanged += ItemsCollectionChanged; - - View = CollectionViewSource.GetDefaultView(Items); - - // initial Notification, so that UI recognizes the value - OnPropertyChanged(nameof(Count)); - - InitializeCommands(); - - BindingOperations.EnableCollectionSynchronization(Items, _itemsLock); - } - - protected BaseListViewModel(IList items, IMessenger messenger) - : this(messenger) - { - AddRange(items); - } - - protected BaseListViewModel(IEnumerable items, IMessenger messenger) - : this(messenger) - { - AddRange(items); - } - - private void InitializeCommands() { RemoveCommand = new RelayCommand(Remove, CanRemove); RemoveRangeCommand = new RelayCommand(RemoveRange, CanRemoveRange); ClearCommand = new RelayCommand(() => Clear(), CanClear); } - private void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) - { - OnPropertyChanged(nameof(Count)); - } - - protected virtual void OnLoaded() + protected BaseListViewModel(IEnumerable items, IMessenger messenger) + : this(messenger) { - IsLoaded = true; - Messenger.Publish(new LoadedMessage(this, this)); + AddRange(items); } /// diff --git a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs new file mode 100644 index 0000000..a6e99e1 --- /dev/null +++ b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs @@ -0,0 +1,16 @@ +using System; +using System.Threading.Tasks; +using Maple.Domain; + +namespace Maple.Core +{ + public abstract class ValidableBaseDataListViewModel : BaseDataListViewModel + where TViewModel : BaseDataViewModel, ISequence + where TModel : class, IBaseObject + { + protected ValidableBaseDataListViewModel(ViewModelServiceContainer container) + : base(container) + { + } + } +} diff --git a/src/Maple.Core/Observables/Virtualization/Base/IDataVirtualizationItemProvider.cs b/src/Maple.Core/Observables/Virtualization/Base/IVirtualizedViewModel.cs similarity index 75% rename from src/Maple.Core/Observables/Virtualization/Base/IDataVirtualizationItemProvider.cs rename to src/Maple.Core/Observables/Virtualization/Base/IVirtualizedViewModel.cs index 0fdd2bb..b8c5213 100644 --- a/src/Maple.Core/Observables/Virtualization/Base/IDataVirtualizationItemProvider.cs +++ b/src/Maple.Core/Observables/Virtualization/Base/IVirtualizedViewModel.cs @@ -2,7 +2,7 @@ namespace Maple.Core { - public interface IDataVirtualizationItemProvider + public interface IVirtualizedViewModel { void ExtendItems(IEnumerable items); void DeflateItem(object item); diff --git a/src/Maple.Core/Observables/Virtualization/DataVirtualizationCollectionView.cs b/src/Maple.Core/Observables/Virtualization/DataVirtualizationCollectionView.cs index aff2cb4..694dbc1 100644 --- a/src/Maple.Core/Observables/Virtualization/DataVirtualizationCollectionView.cs +++ b/src/Maple.Core/Observables/Virtualization/DataVirtualizationCollectionView.cs @@ -7,21 +7,21 @@ namespace Maple.Core { - public class VirtualizationListViewModel : ListCollectionView + public class VirtualizingCollectionViewSource : ListCollectionView { - private readonly IDataVirtualizationItemProvider _sponsor; + private readonly IVirtualizedViewModel _sponsor; private readonly HashSet _deferredItems; private readonly MemoryCache _cache; private readonly CacheItemPolicy _policy; private bool _isDeferred; - public VirtualizationListViewModel(IList list) + public VirtualizingCollectionViewSource(IList list) : base(list) { _deferredItems = new HashSet(); - _sponsor = list as IDataVirtualizationItemProvider; - _cache = new MemoryCache(nameof(VirtualizationListViewModel)); + _sponsor = list as IVirtualizedViewModel; + _cache = new MemoryCache(nameof(VirtualizingCollectionViewSource)); _policy = new CacheItemPolicy() { SlidingExpiration = TimeSpan.FromSeconds(3), diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs b/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs new file mode 100644 index 0000000..0893904 --- /dev/null +++ b/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using Maple.Domain; + +namespace Maple.Core +{ + public abstract class VirtualizationListViewModel : ValidableBaseDataListViewModel, IVirtualizedViewModel, ILoadableViewModel, ISaveableViewModel + where TViewModel : BaseDataViewModel, ISequence + where TModel : class, IBaseObject + { + private bool _isLoaded; + /// + /// Indicates whether the LoadCommand/ the Load Method has been executed yet + /// + public override bool IsLoaded + { + get { return _isLoaded; } + protected set + { + if (value) + SetValue(ref _isLoaded, value, OnChanged: () => Messenger.Publish(new LoadedMessage(this, this))); + } + } + + public int Count => Items?.Count ?? 0; + + /// + /// Gets the load command. + /// + /// + /// The load command. + /// + public override IAsyncCommand LoadCommand => AsyncCommand.Create(LoadAsync, () => !IsLoaded); + /// + /// Gets the refresh command. + /// + /// + /// The refresh command. + /// + public override IAsyncCommand RefreshCommand => AsyncCommand.Create(LoadAsync); + /// + /// Gets the save command. + /// + /// + /// The save command. + /// + public override IAsyncCommand SaveCommand => AsyncCommand.Create(SaveAsync); + + protected VirtualizationListViewModel(ViewModelServiceContainer container) + : base(container) + { + var items = new RangeObservableCollection(); + items.CollectionChanged += ItemsCollectionChanged; + Items = items; + + View = new VirtualizingCollectionViewSource(items); + + // initial Notification, so that UI recognizes the value + OnPropertyChanged(nameof(Count)); + } + + public void DeflateItem(object item) + { + throw new NotImplementedException(); + } + + public void ExtendItems(IEnumerable items) + { + throw new NotImplementedException(); + } + + private void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + OnPropertyChanged(nameof(Count)); + } + } +} diff --git a/src/Maple.Core/Services/Caching/MemoryCacheService.cs b/src/Maple.Core/Services/Caching/MemoryCacheService.cs index ce9120c..a491f2c 100644 --- a/src/Maple.Core/Services/Caching/MemoryCacheService.cs +++ b/src/Maple.Core/Services/Caching/MemoryCacheService.cs @@ -11,7 +11,7 @@ public abstract class MemoryCacheService : ICaching private readonly HashSet _trackedEntries; private readonly MemoryCache _cache; private readonly CacheItemPolicy _policy; - private readonly IDataVirtualizationItemProvider _virtualizationProvider; + private readonly IVirtualizedViewModel _virtualizationProvider; private readonly string _cacheKeyPart; private MemoryCacheService() @@ -26,7 +26,7 @@ private MemoryCacheService() }; } - protected MemoryCacheService(MemoryCache cache, IDataVirtualizationItemProvider virtualizationProvider) + protected MemoryCacheService(MemoryCache cache, IVirtualizedViewModel virtualizationProvider) : this() { _virtualizationProvider = virtualizationProvider ?? throw new ArgumentNullException(nameof(virtualizationProvider), $"{nameof(virtualizationProvider)} {Resources.IsRequired}"); diff --git a/src/Maple.Core/Services/Localization/LocalizationService.cs b/src/Maple.Core/Services/Localization/LocalizationService.cs index 36bd82b..63c5736 100644 --- a/src/Maple.Core/Services/Localization/LocalizationService.cs +++ b/src/Maple.Core/Services/Localization/LocalizationService.cs @@ -54,28 +54,30 @@ public string Translate(string key) return $"!{key}!"; } - public void Save() + public Task Save() { Properties.Settings.Default.StartUpCulture = CurrentLanguage; Properties.Settings.Default.Save(); + + return Task.CompletedTask; } - public void Load() + public Task Load() { _log.Info($"{Resources.Loading} {GetType().Name}"); Thread.CurrentThread.CurrentCulture = Properties.Settings.Default.StartUpCulture; + + return Task.CompletedTask; } public Task SaveAsync() { - Save(); - return Task.CompletedTask; + return Save(); } public Task LoadAsync() { - Load(); - return Task.CompletedTask; + return Load(); } } } diff --git a/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs b/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs index 20c7f34..e2e518f 100644 --- a/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs +++ b/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs @@ -11,7 +11,7 @@ namespace Maple.Data public abstract class MaplePlaylistRepository : IMapleRepository where TModel : class, IBaseObject { - public async Task Save(TModel item) + public async Task SaveAsync(TModel item) { using (var context = new PlaylistContext()) await SaveInternal(item, context).ConfigureAwait(false); diff --git a/src/Maple.Domain/Interfaces/IMapleRepository.cs b/src/Maple.Domain/Interfaces/IMapleRepository.cs index 3cce265..aed1a5e 100644 --- a/src/Maple.Domain/Interfaces/IMapleRepository.cs +++ b/src/Maple.Domain/Interfaces/IMapleRepository.cs @@ -12,6 +12,6 @@ public interface IMapleRepository Task> GetKeysAsync(); Task GetEntryCountAsync(); - Task Save(TModel item); + Task SaveAsync(TModel item); } } \ No newline at end of file diff --git a/src/Maple.Domain/Interfaces/IRefreshable.cs b/src/Maple.Domain/Interfaces/IRefreshable.cs index fdb721b..dac409b 100644 --- a/src/Maple.Domain/Interfaces/IRefreshable.cs +++ b/src/Maple.Domain/Interfaces/IRefreshable.cs @@ -2,9 +2,9 @@ namespace Maple.Domain { - public interface IRefreshable + public interface ILoadAndSaveProvider { - void Save(); + Task Save(); Task LoadAsync(); } } diff --git a/src/Maple.Test/ViewModels/Playlists/PlaylistTests.cs b/src/Maple.Test/ViewModels/Playlists/PlaylistTests.cs index cd433c5..a031355 100644 --- a/src/Maple.Test/ViewModels/Playlists/PlaylistTests.cs +++ b/src/Maple.Test/ViewModels/Playlists/PlaylistTests.cs @@ -34,8 +34,6 @@ public async Task Playlist_ShouldRunConstructorWithoutErrors() var model = _context.CreateModelPlaylist(); var playlist = container.CreatePlaylist(model); - Assert.AreEqual(_context.FullyQualifiedTestClassName, playlist.CreatedBy); - Assert.AreEqual(_context.FullyQualifiedTestClassName, playlist.UpdatedBy); Assert.AreEqual(4, playlist.Count); Assert.AreEqual($"Description for {_context.FullyQualifiedTestClassName} Playlist", playlist.Description); Assert.AreEqual(false, playlist.HasErrors); diff --git a/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs b/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs index f887c96..06a4acb 100644 --- a/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs +++ b/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs @@ -98,9 +98,9 @@ public async Task Playlists_ShouldSave() var playlists = container.Resolve(); repository.ClearReceivedCalls(); - playlists.Save(); + await playlists.SaveAsync().ConfigureAwait(false); - repository.Received(1).Save(NSubstitute.Arg.Any()); + await repository.Received(1).SaveAsync(NSubstitute.Arg.Any()).ConfigureAwait(false); repository.Received(1).Dispose(); } diff --git a/src/Maple/App.xaml.cs b/src/Maple/App.xaml.cs index 2854ef7..64d34e9 100644 --- a/src/Maple/App.xaml.cs +++ b/src/Maple/App.xaml.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; @@ -54,7 +55,7 @@ private async void App_DispatcherUnhandledException(object sender, DispatcherUnh protected override void OnExit(ExitEventArgs e) { - SaveState(); + SaveState().Wait(); DisposeResources(); _backgroundUpdate.Wait(); @@ -158,21 +159,16 @@ private async Task LoadUpdates(ILoggingService log) private IList LoadApplicationData() { - var tasks = new List(); - - foreach (var item in _container.Resolve>()) - tasks.Add(item.LoadAsync()); - - return tasks; + return new List((_container.Resolve>()).ToArray().Select(p => p.LoadAsync())); } - private void SaveState() + private async Task SaveState() { var log = _container.Resolve(); log.Info(Localization.Properties.Resources.SavingState); + var tasks = new List(_container.Resolve>().ToArray().Select(p => p.SaveAsync())); - foreach (var item in _container.Resolve>()) - item.Save(); + await Task.WhenAll(tasks).ConfigureAwait(true); log.Info(Localization.Properties.Resources.SavedState); } diff --git a/src/Maple/Interfaces/IMediaRepository.cs b/src/Maple/Interfaces/IMediaRepository.cs index 5eb7ffa..7b7f1eb 100644 --- a/src/Maple/Interfaces/IMediaRepository.cs +++ b/src/Maple/Interfaces/IMediaRepository.cs @@ -8,20 +8,19 @@ public interface IMediaRepository : IDisposable { bool IsBusy { get; } - void Save(MediaItem viewModel); - void Save(MediaItems viewModel); + Task SaveAsync(MediaItem viewModel); + Task SaveAsync(MediaItems viewModel); Task GetMediaItemByIdAsync(int id); Task> GetMediaItemsAsync(); Task GetMediaItemByPlaylistIdAsync(int id); - - void Save(Playlist viewModel); - void Save(Playlists viewModel); + Task SaveAsync(Playlist viewModel); + Task SaveAsync(Playlists viewModel); Task GetPlaylistByIdAsync(int id); Task> GetPlaylistsAsync(); - void Save(MediaPlayer viewModel); - void Save(MediaPlayers viewModel); + Task SaveAsync(MediaPlayer viewModel); + Task SaveAsync(MediaPlayers viewModel); Task GetMainMediaPlayerAsync(); Task GetMediaPlayerByIdAsync(int id); Task> GetAllOptionalMediaPlayersAsync(); diff --git a/src/Maple/Services/MediaRepository.cs b/src/Maple/Services/MediaRepository.cs index 1a7504a..99c2580 100644 --- a/src/Maple/Services/MediaRepository.cs +++ b/src/Maple/Services/MediaRepository.cs @@ -51,18 +51,18 @@ public MediaRepository(IPlaylistMapper playlistMapper, _busyStack.OnChanged += (hasItems) => { IsBusy = hasItems; }; } - public void Save(MediaItem viewModel) + public async Task SaveAsync(MediaItem viewModel) { using (_busyStack.GetToken()) - _mediaItemRepository.Save(viewModel.Model); + await _mediaItemRepository.SaveAsync(viewModel.Model).ConfigureAwait(false); } - public void Save(MediaItems viewModel) + public async Task SaveAsync(MediaItems viewModel) { using (_busyStack.GetToken()) { - foreach (var item in viewModel.Items) - Save(item); + var tasks = new List(viewModel.Items.Select(p => SaveAsync(p))); + await Task.WhenAll(tasks).ConfigureAwait(true); } } @@ -71,7 +71,7 @@ public async Task GetMediaItemByIdAsync(int id) using (_busyStack.GetToken()) { var item = await _mediaItemRepository.GetByIdAsync(id) - .ConfigureAwait(true); + .ConfigureAwait(false); return _mediaItemMapper.Get(item); } } @@ -81,7 +81,7 @@ public async Task> GetMediaItemsAsync() using (_busyStack.GetToken()) { var items = await _mediaItemRepository.GetAsync() - .ConfigureAwait(true); + .ConfigureAwait(false); return items.Select(p => _mediaItemMapper.Get(p)) .ToList(); } @@ -92,26 +92,26 @@ public async Task GetMediaItemByPlaylistIdAsync(int id) using (_busyStack.GetToken()) { var item = await _mediaItemRepository.GetMediaItemByPlaylistIdAsync(id) - .ConfigureAwait(true); + .ConfigureAwait(false); return _mediaItemMapper.Get(item); } } - public void Save(Playlist viewModel) + public async Task SaveAsync(Playlist viewModel) { if (!viewModel.IsChanged) return; using (_busyStack.GetToken()) - _playlistRepository.Save(viewModel.Model); + await _playlistRepository.SaveAsync(viewModel.Model).ConfigureAwait(false); } - public void Save(Playlists viewModel) + public async Task SaveAsync(Playlists viewModel) { using (_busyStack.GetToken()) { - foreach (var item in viewModel.Items) - Save(item); + var tasks = new List(viewModel.Items.Select(p => SaveAsync(p))); + await Task.WhenAll(tasks).ConfigureAwait(false); ; } } @@ -120,7 +120,7 @@ public async Task GetPlaylistByIdAsync(int id) using (_busyStack.GetToken()) { var item = await _playlistRepository.GetByIdAsync(id) - .ConfigureAwait(true); + .ConfigureAwait(false); return _playlistMapper.Get(item); } } @@ -130,24 +130,24 @@ public async Task> GetPlaylistsAsync() using (_busyStack.GetToken()) { var items = await _playlistRepository.GetAsync() - .ConfigureAwait(true); + .ConfigureAwait(false); return items.Select(p => _playlistMapper.Get(p)) .ToList(); } } - public void Save(MediaPlayer viewModel) + public async Task SaveAsync(MediaPlayer viewModel) { using (_busyStack.GetToken()) - _mediaPlayerRepository.Save(viewModel.Model); + await _mediaPlayerRepository.SaveAsync(viewModel.Model).ConfigureAwait(false); } - public void Save(MediaPlayers viewModel) + public async Task SaveAsync(MediaPlayers viewModel) { using (_busyStack.GetToken()) { - foreach (var item in viewModel.Items) - Save(item); + var tasks = new List(viewModel.Items.Select(p => SaveAsync(p))); + await Task.WhenAll(tasks).ConfigureAwait(true); } } @@ -156,7 +156,7 @@ public async Task GetMainMediaPlayerAsync() using (_busyStack.GetToken()) { var item = await _mediaPlayerRepository.GetMainMediaPlayerAsync() - .ConfigureAwait(true); + .ConfigureAwait(false); return _mediaPlayerMapper.GetMain(item, _playlistMapper.Get(item.Playlist)); } } @@ -166,7 +166,7 @@ public async Task GetMediaPlayerByIdAsync(int id) using (_busyStack.GetToken()) { var item = await _mediaPlayerRepository.GetByIdAsync(id) - .ConfigureAwait(true); + .ConfigureAwait(false); return _mediaPlayerMapper.Get(item); } } @@ -176,7 +176,7 @@ public async Task> GetAllOptionalMediaPlayersAsync() using (_busyStack.GetToken()) { var items = await _mediaPlayerRepository.GetOptionalMediaPlayersAsync() - .ConfigureAwait(true); + .ConfigureAwait(false); return items.Select(p => _mediaPlayerMapper.Get(p)) .ToList(); } diff --git a/src/Maple/Utils/DependencyInjectionFactory.cs b/src/Maple/Utils/DependencyInjectionFactory.cs index b0c7e3e..ea11807 100644 --- a/src/Maple/Utils/DependencyInjectionFactory.cs +++ b/src/Maple/Utils/DependencyInjectionFactory.cs @@ -27,9 +27,6 @@ IContainer InitializeContainer() c.Resolve().LoadAsync(); - //if (Debugger.IsAttached) - // Debugging(); - return c; } @@ -44,10 +41,10 @@ void RegisterViewModels() // TODO register disposeables // save-/loadable ViewModels - c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(IPlaylistsViewModel) }, typeof(Playlists), Reuse.Singleton); - c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(IMediaPlayersViewModel) }, typeof(MediaPlayers), Reuse.Singleton, setup: Setup.With(allowDisposableTransient: true)); - c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(ICultureViewModel) }, typeof(Cultures), Reuse.Singleton); - c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(IUIColorsViewModel) }, typeof(UIColorsViewModel), Reuse.Singleton); + c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(ISaveableViewModel), typeof(IPlaylistsViewModel) }, typeof(Playlists), Reuse.Singleton); + c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(ISaveableViewModel), typeof(IMediaPlayersViewModel) }, typeof(MediaPlayers), Reuse.Singleton, setup: Setup.With(allowDisposableTransient: true)); + c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(ISaveableViewModel), typeof(ICultureViewModel) }, typeof(Cultures), Reuse.Singleton); + c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(ISaveableViewModel), typeof(IUIColorsViewModel) }, typeof(UIColorsViewModel), Reuse.Singleton); //generic ViewModels c.Register(Reuse.Singleton, setup: Setup.With(allowDisposableTransient: true)); diff --git a/src/Maple/Utils/Validation/PlaylistValidator.cs b/src/Maple/Utils/Validation/PlaylistValidator.cs index 6a800b0..490d1a1 100644 --- a/src/Maple/Utils/Validation/PlaylistValidator.cs +++ b/src/Maple/Utils/Validation/PlaylistValidator.cs @@ -16,11 +16,6 @@ public PlaylistValidator(ILocalizationService translationService, IValidator playlist.PrivacyStatus).NotNull(); - RuleFor(playlist => playlist.UpdatedBy).NotEmpty(); - RuleFor(playlist => playlist.UpdatedBy).NotEmpty(); - RuleFor(playlist => playlist.CreatedBy).NotEmpty(); - RuleFor(playlist => playlist.CreatedOn).NotEmpty(); - RuleFor(playlist => playlist.RepeatModes).NotEmpty(); RuleFor(playlist => playlist.RepeatMode).NotNull(); diff --git a/src/Maple/ViewModels/Interfaces/IMediaItemsViewModel.cs b/src/Maple/ViewModels/Interfaces/IMediaItemsViewModel.cs index 3ebd2bb..4d1748d 100644 --- a/src/Maple/ViewModels/Interfaces/IMediaItemsViewModel.cs +++ b/src/Maple/ViewModels/Interfaces/IMediaItemsViewModel.cs @@ -4,12 +4,10 @@ namespace Maple { - public interface IMediaItemsViewModel : ISaveableViewModel + public interface IMediaItemsViewModel : ILoadableViewModel, ISaveableViewModel { IReadOnlyCollection Items { get; } void Add(Playlist playlist); - Task LoadAsync(); - void Save(); } } \ No newline at end of file diff --git a/src/Maple/ViewModels/MediaItems/MediaItem.cs b/src/Maple/ViewModels/MediaItems/MediaItem.cs index 8354ba2..b93098b 100644 --- a/src/Maple/ViewModels/MediaItems/MediaItem.cs +++ b/src/Maple/ViewModels/MediaItems/MediaItem.cs @@ -78,34 +78,6 @@ public bool IsSelected set { SetValue(ref _isSelected, value); } } - private string _createdBy; - public string CreatedBy - { - get { return _createdBy; } - private set { SetValue(ref _createdBy, value, OnChanged: () => Model.CreatedBy = value); } - } - - private string _updatedBy; - public string UpdatedBy - { - get { return _updatedBy; } - set { SetValue(ref _updatedBy, value, OnChanged: () => Model.UpdatedBy = value); } - } - - private DateTime _updatedOn; - public DateTime UpdatedOn - { - get { return _updatedOn; } - set { SetValue(ref _updatedOn, value, OnChanged: () => Model.UpdatedOn = value); } - } - - private DateTime _createdOn; - public DateTime CreatedOn - { - get { return _updatedOn; } - private set { SetValue(ref _updatedOn, value, OnChanged: () => Model.CreatedOn = value); } - } - private Playlist _playlist; public Playlist Playlist { @@ -135,10 +107,6 @@ public MediaItem(MediaItemModel model, IValidator validator, IMesseng _duration = TimeSpan.FromTicks(model.Duration); _privacyStatus = (PrivacyStatus)model.PrivacyStatus; _mediaItemType = (MediaItemType)model.MediaItemType; - _createdBy = model.CreatedBy; - _createdOn = model.CreatedOn; - _updatedBy = model.UpdatedBy; - _updatedOn = model.UpdatedOn; Validate(); } diff --git a/src/Maple/ViewModels/MediaItems/MediaItems.cs b/src/Maple/ViewModels/MediaItems/MediaItems.cs index bbef663..3a9b45f 100644 --- a/src/Maple/ViewModels/MediaItems/MediaItems.cs +++ b/src/Maple/ViewModels/MediaItems/MediaItems.cs @@ -7,7 +7,7 @@ namespace Maple { - public class MediaItems : BaseDataListViewModel, IMediaItemsViewModel + public class MediaItems : VirtualizationListViewModel, IMediaItemsViewModel { private readonly Func _repositoryFactory; private readonly IMediaItemMapper _mediaItemMapper; @@ -25,15 +25,6 @@ public void Add(Playlist playlist) Add(_mediaItemMapper.GetNewMediaItem(sequence, playlist)); } - private void SaveInternal() - { - _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.MediaItems))}"); - using (var context = _repositoryFactory()) - { - context.Save(this); - } - } - public override async Task LoadAsync() { _log.Info($"{_translationService.Translate(nameof(Resources.Loading))} {_translationService.Translate(nameof(Resources.MediaItems))}"); @@ -46,12 +37,16 @@ public override async Task LoadAsync() } SelectedItem = Items.FirstOrDefault(); - OnLoaded(); + IsLoaded = true; } - public override void Save() + public override async Task SaveAsync() { - SaveInternal(); + _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.MediaItems))}"); + using (var context = _repositoryFactory()) + { + await context.SaveAsync(this).ConfigureAwait(true); + } } } } diff --git a/src/Maple/ViewModels/MediaPlayer/AudioDevice.cs b/src/Maple/ViewModels/MediaPlayer/AudioDevice.cs index 066b170..b94a5ea 100644 --- a/src/Maple/ViewModels/MediaPlayer/AudioDevice.cs +++ b/src/Maple/ViewModels/MediaPlayer/AudioDevice.cs @@ -6,8 +6,6 @@ namespace Maple public class AudioDevice : ObservableObject, IIsSelected, ISequence, IAudioDevice { private bool _isSelected; - - public bool IsSelected { get { return _isSelected; } diff --git a/src/Maple/ViewModels/MediaPlayer/MediaPlayer.cs b/src/Maple/ViewModels/MediaPlayer/MediaPlayer.cs index 8a79a5a..7fc705f 100644 --- a/src/Maple/ViewModels/MediaPlayer/MediaPlayer.cs +++ b/src/Maple/ViewModels/MediaPlayer/MediaPlayer.cs @@ -92,34 +92,6 @@ public bool IsPrimary protected set { SetValue(ref _isPrimary, value, OnChanged: () => Model.IsPrimary = value); } } - private string _createdBy; - public string CreatedBy - { - get { return _createdBy; } - set { SetValue(ref _createdBy, value, OnChanged: () => Model.CreatedBy = value); } - } - - private string _updatedBy; - public string UpdatedBy - { - get { return _updatedBy; } - set { SetValue(ref _updatedBy, value, OnChanged: () => Model.UpdatedBy = value); } - } - - private DateTime _updatedOn; - public DateTime UpdatedOn - { - get { return _updatedOn; } - set { SetValue(ref _updatedOn, value, OnChanged: () => Model.UpdatedOn = value); } - } - - private DateTime _createdOn; - public DateTime CreatedOn - { - get { return _updatedOn; } - set { SetValue(ref _updatedOn, value, OnChanged: () => Model.CreatedOn = value); } - } - public MediaPlayer(ViewModelServiceContainer container, IMediaPlayer player, IValidator validator, AudioDevices devices, Playlist playlist, MediaPlayerModel model) : base(model, validator, container.Messenger) { @@ -130,11 +102,6 @@ public MediaPlayer(ViewModelServiceContainer container, IMediaPlayer player, IVa _audioDevices = devices; _sequence = model.Sequence; - _createdBy = model.CreatedBy; - _createdOn = model.CreatedOn; - _updatedBy = model.UpdatedBy; - _updatedOn = model.UpdatedOn; - if (AudioDevices.Items.Count > 0) Player.AudioDevice = AudioDevices.Items.FirstOrDefault(p => p.Name == Model.DeviceName) ?? AudioDevices[0]; diff --git a/src/Maple/ViewModels/MediaPlayer/MediaPlayers.cs b/src/Maple/ViewModels/MediaPlayer/MediaPlayers.cs index 1a735fe..b6d81dc 100644 --- a/src/Maple/ViewModels/MediaPlayer/MediaPlayers.cs +++ b/src/Maple/ViewModels/MediaPlayer/MediaPlayers.cs @@ -7,7 +7,7 @@ namespace Maple { - public class MediaPlayers : BaseDataListViewModel, IMediaPlayersViewModel + public class MediaPlayers : VirtualizationListViewModel, IMediaPlayersViewModel { private readonly Func _playerFactory; private readonly AudioDevices _devices; @@ -41,15 +41,6 @@ public MediaPlayers(ViewModelServiceContainer container, _notificationService = container.NotificationService; } - private void SaveInternal() - { - _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.MediaPlayers))}"); - using (var context = _repositoryFactory()) - { - context.Save(this); - } - } - public void Add() { var sequence = _sequenceProvider.Get(Items.Select(p => (ISequence)p).ToList()); @@ -77,9 +68,13 @@ protected override void Dispose(bool disposing) Disposed = true; } - public override void Save() + public override async Task SaveAsync() { - SaveInternal(); + _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.MediaPlayers))}"); + using (var context = _repositoryFactory()) + { + await context.SaveAsync(this).ConfigureAwait(true); + } } public override async Task LoadAsync() @@ -98,7 +93,7 @@ public override async Task LoadAsync() AddRange(others); } - OnLoaded(); + IsLoaded = true; } } } diff --git a/src/Maple/ViewModels/Playlists/Playlist.cs b/src/Maple/ViewModels/Playlists/Playlist.cs index 6b55db7..0e541c4 100644 --- a/src/Maple/ViewModels/Playlists/Playlist.cs +++ b/src/Maple/ViewModels/Playlists/Playlist.cs @@ -41,26 +41,6 @@ public int Id get { return Model.Id; } } - public string CreatedBy - { - get { return Model.CreatedBy; } - } - - public string UpdatedBy - { - get { return Model.UpdatedBy; } - } - - public DateTime UpdatedOn - { - get { return Model.UpdatedOn; } - } - - public DateTime CreatedOn - { - get { return Model.CreatedOn; } - } - public MediaItem this[int index] { get { return _items[index]; } diff --git a/src/Maple/ViewModels/Playlists/Playlists.cs b/src/Maple/ViewModels/Playlists/Playlists.cs index 6547665..0b62f6e 100644 --- a/src/Maple/ViewModels/Playlists/Playlists.cs +++ b/src/Maple/ViewModels/Playlists/Playlists.cs @@ -7,7 +7,7 @@ namespace Maple { - public class Playlists : BaseDataListViewModel, ISaveableViewModel, IPlaylistsViewModel + public class Playlists : VirtualizationListViewModel, ISaveableViewModel, IPlaylistsViewModel { private readonly Func _repositoryFactory; private readonly IPlaylistMapper _playlistMapper; @@ -21,15 +21,6 @@ public Playlists(ViewModelServiceContainer container, IPlaylistMapper playlistMa AddCommand = new RelayCommand(Add, CanAdd); } - private void SaveInternal() - { - _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.Playlists))}"); - using (var context = _repositoryFactory()) - { - context.Save(this); - } - } - public void Add() { Add(_playlistMapper.GetNewPlaylist()); @@ -40,9 +31,13 @@ public bool CanAdd() return Items != null; } - public override void Save() + public override async Task SaveAsync() { - SaveInternal(); + _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.Playlists))}"); + using (var context = _repositoryFactory()) + { + await context.SaveAsync(this).ConfigureAwait(true); + } } public override async Task LoadAsync() @@ -57,7 +52,7 @@ public override async Task LoadAsync() } SelectedItem = Items.FirstOrDefault(); - OnLoaded(); + IsLoaded = true; } } } diff --git a/src/Maple/ViewModels/Settings/Cultures.cs b/src/Maple/ViewModels/Settings/Cultures.cs index b48b499..2aa2792 100644 --- a/src/Maple/ViewModels/Settings/Cultures.cs +++ b/src/Maple/ViewModels/Settings/Cultures.cs @@ -1,6 +1,5 @@ using System.Linq; using System.Threading.Tasks; -using System.Windows.Input; using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; @@ -12,9 +11,23 @@ public class Cultures : BaseListViewModel, ICultureViewModel private readonly ILocalizationService _manager; private readonly ILoggingService _log; - public ICommand RefreshCommand => AsyncCommand.Create(LoadAsync); - public ICommand LoadCommand => AsyncCommand.Create(LoadAsync, () => !IsLoaded); - public ICommand SaveCommand => new RelayCommand(Save); + public IAsyncCommand RefreshCommand => AsyncCommand.Create(LoadAsync); + public IAsyncCommand LoadCommand => AsyncCommand.Create(LoadAsync, () => !IsLoaded); + public IAsyncCommand SaveCommand => AsyncCommand.Create(Save); + + private bool _isLoaded; + /// + /// Indicates whether the LoadCommand/ the Load Method has been executed yet + /// + public bool IsLoaded + { + get { return _isLoaded; } + protected set + { + if (value) + SetValue(ref _isLoaded, value, OnChanged: () => Messenger.Publish(new LoadedMessage(this, this))); + } + } public Cultures(ViewModelServiceContainer container) : base(container.Messenger) @@ -30,10 +43,12 @@ private void SyncCulture() _manager.CurrentLanguage = SelectedItem.Model; } - public void Save() + public Task Save() { _log.Info($"{Resources.Saving} {Resources.Options}"); _manager.Save(); + + return Task.CompletedTask; } public Task SaveAsync() @@ -42,7 +57,6 @@ public Task SaveAsync() { _log.Info($"{Resources.Saving} {Resources.Options}"); _manager.Save(); - }); } diff --git a/src/Maple/ViewModels/Settings/UIColorsViewModel.cs b/src/Maple/ViewModels/Settings/UIColorsViewModel.cs index c6c0760..26f9a68 100644 --- a/src/Maple/ViewModels/Settings/UIColorsViewModel.cs +++ b/src/Maple/ViewModels/Settings/UIColorsViewModel.cs @@ -85,21 +85,21 @@ public ICommand ApplyAccentCommand /// /// The refresh command. /// - public ICommand RefreshCommand => new RelayCommand(Load); + public IAsyncCommand RefreshCommand => AsyncCommand.Create(Load); /// /// Gets the load command. /// /// /// The load command. /// - public ICommand LoadCommand => new RelayCommand(Load, () => !IsLoaded); + public IAsyncCommand LoadCommand => AsyncCommand.Create(Load, () => !IsLoaded); /// /// Gets the save command. /// /// /// The save command. /// - public ICommand SaveCommand => new RelayCommand(Save); + public IAsyncCommand SaveCommand => AsyncCommand.Create(Save); /// /// Gets the swatches. @@ -166,7 +166,7 @@ public void OnPrimaryColorChanged(UiPrimaryColorChangedMessage args) /// /// Saves this instance. /// - public void Save() + public Task Save() { _log.Info($"{Resources.Saving} {Resources.Themes}"); @@ -175,12 +175,14 @@ public void Save() Properties.Settings.Default.UseDarkTheme = _isDark; Properties.Settings.Default.Save(); + + return Task.CompletedTask; } /// /// Loads this instance. /// - public void Load() + public Task Load() { _log.Info($"{Resources.Loading} {Resources.Themes}"); @@ -195,11 +197,12 @@ public void Load() ApplyBase(this, Properties.Settings.Default.UseDarkTheme); _messenger.Publish(new LoadedMessage(this, this)); + return Task.CompletedTask; } - public Task SaveAsync() + public async Task SaveAsync() { - return Task.Run(() => Save()); + await Save().ConfigureAwait(true); } public Task LoadAsync() From bf6604d1b32abf5e1d16314d6d74b9c2d6ad051b Mon Sep 17 00:00:00 2001 From: Insire Date: Mon, 8 Jan 2018 19:15:16 +0100 Subject: [PATCH 03/16] refactoring --- src/Maple.Core/DiagnosticReport.cs | 2 +- src/Maple.Core/Maple.Core.csproj | 8 +- .../Base}/ILoadableViewModel.cs | 0 .../Base}/ISaveableViewModel.cs | 0 .../ValidableBaseDataListViewModel.cs | 6 +- .../VirtualizationListViewModel.cs | 20 +- .../Services/Caching/WeakReferenceCache.cs | 5 - .../Localization}/ILocalizationService.cs | 9 +- src/Maple.Domain/Interfaces/IRefreshable.cs | 10 - src/Maple.Domain/Maple.Domain.csproj | 1 - .../Properties/Resources.Designer.cs | 178 +++++++++--------- .../Interfaces/IConfigurableWindowSettings.cs | 5 +- .../Interfaces/IIocFrameworkElement.cs | 0 src/Maple/Maple.csproj | 4 +- src/Maple/Properties/AssemblyInfo.cs | 3 +- src/Maple/UI/Base/ConfigurableWindow.cs | 1 - .../UI/Base/ConfigurableWindowSettings.cs | 1 - .../UI/UserControls/MediaPlayerPage.xaml.cs | 4 +- .../UI/UserControls/MediaPlayersPage.xaml.cs | 4 +- .../Options/ColorOptionsPage.xaml.cs | 4 +- .../UserControls/Options/OptionsPage.xaml.cs | 4 +- .../Playlist/NewPlaylistOptionsPage.xaml.cs | 4 +- .../Playlist/NewPlaylistPage.xaml.cs | 4 +- .../Playlist/PlaylistsPage.xaml.cs | 4 +- .../Mappers/{ => Base}/MapperExtensions.cs | 0 .../Utils/Validation/Base/BaseValidator.cs | 1 - .../Utils/Validation/MediaItemValidator.cs | 1 - .../Utils/Validation/MediaPlayerValidator.cs | 1 - .../Utils/Validation/PlaylistValidator.cs | 1 - .../Utils/Validation/PlaylistsValidator.cs | 1 - .../Interfaces/IMediaItemsViewModel.cs | 1 - src/Maple/ViewModels/Navigation/Scenes.cs | 1 - 32 files changed, 115 insertions(+), 173 deletions(-) rename src/Maple.Core/{Interfaces => Observables/Base}/ILoadableViewModel.cs (100%) rename src/Maple.Core/{Interfaces => Observables/Base}/ISaveableViewModel.cs (100%) rename src/Maple.Core/{Interfaces => Services/Localization}/ILocalizationService.cs (90%) delete mode 100644 src/Maple.Domain/Interfaces/IRefreshable.cs rename src/{Maple.Core => Maple}/Interfaces/IConfigurableWindowSettings.cs (94%) rename src/{Maple.Core => Maple}/Interfaces/IIocFrameworkElement.cs (100%) rename src/Maple/Utils/Mappers/{ => Base}/MapperExtensions.cs (100%) diff --git a/src/Maple.Core/DiagnosticReport.cs b/src/Maple.Core/DiagnosticReport.cs index 889713b..3572867 100644 --- a/src/Maple.Core/DiagnosticReport.cs +++ b/src/Maple.Core/DiagnosticReport.cs @@ -6,8 +6,8 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Text; -using Microsoft.Win32; using Humanizer; +using Microsoft.Win32; namespace Maple.Core { diff --git a/src/Maple.Core/Maple.Core.csproj b/src/Maple.Core/Maple.Core.csproj index 07a3cca..aeb7c04 100644 --- a/src/Maple.Core/Maple.Core.csproj +++ b/src/Maple.Core/Maple.Core.csproj @@ -107,16 +107,14 @@ - + - - - + @@ -146,7 +144,7 @@ Settings.settings - + diff --git a/src/Maple.Core/Interfaces/ILoadableViewModel.cs b/src/Maple.Core/Observables/Base/ILoadableViewModel.cs similarity index 100% rename from src/Maple.Core/Interfaces/ILoadableViewModel.cs rename to src/Maple.Core/Observables/Base/ILoadableViewModel.cs diff --git a/src/Maple.Core/Interfaces/ISaveableViewModel.cs b/src/Maple.Core/Observables/Base/ISaveableViewModel.cs similarity index 100% rename from src/Maple.Core/Interfaces/ISaveableViewModel.cs rename to src/Maple.Core/Observables/Base/ISaveableViewModel.cs diff --git a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs index a6e99e1..6478334 100644 --- a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs @@ -1,6 +1,4 @@ -using System; -using System.Threading.Tasks; -using Maple.Domain; +using Maple.Domain; namespace Maple.Core { @@ -12,5 +10,7 @@ protected ValidableBaseDataListViewModel(ViewModelServiceContainer container) : base(container) { } + + // TODO add logic for handling INotifyDataErrorInfo for children and on this } } diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs b/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs index 0893904..77cbea4 100644 --- a/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs +++ b/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs @@ -25,26 +25,8 @@ protected set public int Count => Items?.Count ?? 0; - /// - /// Gets the load command. - /// - /// - /// The load command. - /// public override IAsyncCommand LoadCommand => AsyncCommand.Create(LoadAsync, () => !IsLoaded); - /// - /// Gets the refresh command. - /// - /// - /// The refresh command. - /// - public override IAsyncCommand RefreshCommand => AsyncCommand.Create(LoadAsync); - /// - /// Gets the save command. - /// - /// - /// The save command. - /// + public override IAsyncCommand RefreshCommand => AsyncCommand.Create(LoadAsync, () => IsLoaded); public override IAsyncCommand SaveCommand => AsyncCommand.Create(SaveAsync); protected VirtualizationListViewModel(ViewModelServiceContainer container) diff --git a/src/Maple.Core/Services/Caching/WeakReferenceCache.cs b/src/Maple.Core/Services/Caching/WeakReferenceCache.cs index 2346e43..134f988 100644 --- a/src/Maple.Core/Services/Caching/WeakReferenceCache.cs +++ b/src/Maple.Core/Services/Caching/WeakReferenceCache.cs @@ -1,9 +1,4 @@ using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Collections.Concurrent; namespace Maple.Core diff --git a/src/Maple.Core/Interfaces/ILocalizationService.cs b/src/Maple.Core/Services/Localization/ILocalizationService.cs similarity index 90% rename from src/Maple.Core/Interfaces/ILocalizationService.cs rename to src/Maple.Core/Services/Localization/ILocalizationService.cs index d82a308..c6213f2 100644 --- a/src/Maple.Core/Interfaces/ILocalizationService.cs +++ b/src/Maple.Core/Services/Localization/ILocalizationService.cs @@ -1,16 +1,16 @@ using System.Collections.Generic; using System.ComponentModel; using System.Globalization; -using Maple.Domain; +using System.Threading.Tasks; -namespace Maple.Core +namespace Maple { /// /// /// /// /// - public interface ILocalizationService : INotifyPropertyChanged, ILoadAndSaveProvider + public interface ILocalizationService : INotifyPropertyChanged { /// /// Gets or sets the current language. @@ -32,5 +32,8 @@ public interface ILocalizationService : INotifyPropertyChanged, ILoadAndSaveProv /// The key. /// string Translate(string key); + + Task Save(); + Task LoadAsync(); } } diff --git a/src/Maple.Domain/Interfaces/IRefreshable.cs b/src/Maple.Domain/Interfaces/IRefreshable.cs deleted file mode 100644 index dac409b..0000000 --- a/src/Maple.Domain/Interfaces/IRefreshable.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Threading.Tasks; - -namespace Maple.Domain -{ - public interface ILoadAndSaveProvider - { - Task Save(); - Task LoadAsync(); - } -} diff --git a/src/Maple.Domain/Maple.Domain.csproj b/src/Maple.Domain/Maple.Domain.csproj index 0c1d2c2..df0120f 100644 --- a/src/Maple.Domain/Maple.Domain.csproj +++ b/src/Maple.Domain/Maple.Domain.csproj @@ -64,7 +64,6 @@ - diff --git a/src/Maple.Localization/Properties/Resources.Designer.cs b/src/Maple.Localization/Properties/Resources.Designer.cs index fbdb378..53dc171 100644 --- a/src/Maple.Localization/Properties/Resources.Designer.cs +++ b/src/Maple.Localization/Properties/Resources.Designer.cs @@ -8,10 +8,10 @@ // //------------------------------------------------------------------------------ -namespace Maple.Localization.Properties { - using System; - - +namespace Maple.Localization.Properties +{ + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -23,15 +23,15 @@ namespace Maple.Localization.Properties { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources { - + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// @@ -45,7 +45,7 @@ internal Resources() { return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. @@ -59,7 +59,7 @@ internal Resources() { resourceCulture = value; } } - + /// /// Looks up a localized string similar to Ok. /// @@ -68,7 +68,7 @@ public static string Accept { return ResourceManager.GetString("Accept", resourceCulture); } } - + /// /// Looks up a localized string similar to Hinzufügen. /// @@ -77,7 +77,7 @@ public static string Add { return ResourceManager.GetString("Add", resourceCulture); } } - + /// /// Looks up a localized string similar to Anwendung wird gestartet. /// @@ -86,7 +86,7 @@ public static string AppStart { return ResourceManager.GetString("AppStart", resourceCulture); } } - + /// /// Looks up a localized string similar to Wiedergabegerät. /// @@ -95,7 +95,7 @@ public static string AudioDevice { return ResourceManager.GetString("AudioDevice", resourceCulture); } } - + /// /// Looks up a localized string similar to Abbrechen. /// @@ -104,7 +104,7 @@ public static string Cancel { return ResourceManager.GetString("Cancel", resourceCulture); } } - + /// /// Looks up a localized string similar to Leeren. /// @@ -113,7 +113,7 @@ public static string Clear { return ResourceManager.GetString("Clear", resourceCulture); } } - + /// /// Looks up a localized string similar to Schließen. /// @@ -122,7 +122,7 @@ public static string Close { return ResourceManager.GetString("Close", resourceCulture); } } - + /// /// Looks up a localized string similar to Zu den Farbprofilen wechseln. /// @@ -131,7 +131,7 @@ public static string ColorOptionsCommand { return ResourceManager.GetString("ColorOptionsCommand", resourceCulture); } } - + /// /// Looks up a localized string similar to Anzahl. /// @@ -140,7 +140,7 @@ public static string Count { return ResourceManager.GetString("Count", resourceCulture); } } - + /// /// Looks up a localized string similar to Löschen. /// @@ -149,7 +149,7 @@ public static string Delete { return ResourceManager.GetString("Delete", resourceCulture); } } - + /// /// Looks up a localized string similar to Beschreibung. /// @@ -158,7 +158,7 @@ public static string Description { return ResourceManager.GetString("Description", resourceCulture); } } - + /// /// Looks up a localized string similar to Es ist bereits ein Dialog geöffnet. Es kann kein Weiterer geöffnet werden. /// @@ -167,7 +167,7 @@ public static string DialogOpenAlready { return ResourceManager.GetString("DialogOpenAlready", resourceCulture); } } - + /// /// Looks up a localized string similar to Dirigent. /// @@ -176,7 +176,7 @@ public static string Director { return ResourceManager.GetString("Director", resourceCulture); } } - + /// /// Looks up a localized string similar to Speichert geleert. /// @@ -185,7 +185,7 @@ public static string DisposedState { return ResourceManager.GetString("DisposedState", resourceCulture); } } - + /// /// Looks up a localized string similar to Speicher wird geleert. /// @@ -194,7 +194,7 @@ public static string DisposingState { return ResourceManager.GetString("DisposingState", resourceCulture); } } - + /// /// Looks up a localized string similar to Dauer. /// @@ -203,7 +203,7 @@ public static string Duration { return ResourceManager.GetString("Duration", resourceCulture); } } - + /// /// Looks up a localized string similar to Ändern. /// @@ -212,7 +212,7 @@ public static string Edit { return ResourceManager.GetString("Edit", resourceCulture); } } - + /// /// Looks up a localized string similar to Sprache ändern. /// @@ -221,7 +221,7 @@ public static string EditLanguage { return ResourceManager.GetString("EditLanguage", resourceCulture); } } - + /// /// Looks up a localized string similar to Liste darf nicht null oder leer sein.. /// @@ -230,7 +230,7 @@ public static string ExceptionMessageCollectionNullOrEmpty { return ResourceManager.GetString("ExceptionMessageCollectionNullOrEmpty", resourceCulture); } } - + /// /// Looks up a localized string similar to Werte müssen gleich sein.. /// @@ -239,7 +239,7 @@ public static string ExceptionMessageEqualValues { return ResourceManager.GetString("ExceptionMessageEqualValues", resourceCulture); } } - + /// /// Looks up a localized string similar to Die angegebene Bedingung ist falsch.. /// @@ -248,7 +248,7 @@ public static string ExceptionMessageFalseCondition { return ResourceManager.GetString("ExceptionMessageFalseCondition", resourceCulture); } } - + /// /// Looks up a localized string similar to Folgendes Verzeichnis wurde nicht gefunden:. /// @@ -257,7 +257,7 @@ public static string ExceptionMessageMissingDirectory { return ResourceManager.GetString("ExceptionMessageMissingDirectory", resourceCulture); } } - + /// /// Looks up a localized string similar to Folgende Datei wurde nicht gefunden:. /// @@ -266,7 +266,7 @@ public static string ExceptionMessageMissingFile { return ResourceManager.GetString("ExceptionMessageMissingFile", resourceCulture); } } - + /// /// Looks up a localized string similar to Werte dürfen nicht gleich sein.. /// @@ -275,7 +275,7 @@ public static string ExceptionMessageNotEqualValues { return ResourceManager.GetString("ExceptionMessageNotEqualValues", resourceCulture); } } - + /// /// Looks up a localized string similar to String darf nicht null, leer oder nur Leerraum enthalten.. /// @@ -284,7 +284,7 @@ public static string ExceptionMessageStringNullEmpyOrWhiteSpace { return ResourceManager.GetString("ExceptionMessageStringNullEmpyOrWhiteSpace", resourceCulture); } } - + /// /// Looks up a localized string similar to Die angegebene Bedingung ist wahr.. /// @@ -293,7 +293,7 @@ public static string ExceptionMessageTrueCondition { return ResourceManager.GetString("ExceptionMessageTrueCondition", resourceCulture); } } - + /// /// Looks up a localized string similar to Ein unerwarteter Fehler ist aufgetreten.. /// @@ -302,7 +302,7 @@ public static string ExceptionMessageUnhandled { return ResourceManager.GetString("ExceptionMessageUnhandled", resourceCulture); } } - + /// /// Looks up a localized string similar to Eine Wiedergabeliste aus einer Datei importieren. /// @@ -311,7 +311,7 @@ public static string FilePlaylistImport { return ResourceManager.GetString("FilePlaylistImport", resourceCulture); } } - + /// /// Looks up a localized string similar to Filter. /// @@ -320,7 +320,7 @@ public static string Filter { return ResourceManager.GetString("Filter", resourceCulture); } } - + /// /// Looks up a localized string similar to Eine Wiedergabeliste anhand eines Ordners aus dem Dateisystem generieren und importieren. /// @@ -329,7 +329,7 @@ public static string FolderPlaylistImport { return ResourceManager.GetString("FolderPlaylistImport", resourceCulture); } } - + /// /// Looks up a localized string similar to Projektseite auf GitHub.com öffnen. /// @@ -338,7 +338,7 @@ public static string GithubPageCommand { return ResourceManager.GetString("GithubPageCommand", resourceCulture); } } - + /// /// Looks up a localized string similar to https://github.com/Insire/InsireBot-V2. /// @@ -347,7 +347,7 @@ public static string GithubProjectLink { return ResourceManager.GetString("GithubProjectLink", resourceCulture); } } - + /// /// Looks up a localized string similar to Auf der Datenbank befinden sich eine ungültige Anzahl an Einträgen für den Standardmediaplayer. /// @@ -356,7 +356,7 @@ public static string InvalidMediaplayerCountOnDBException { return ResourceManager.GetString("InvalidMediaplayerCountOnDBException", resourceCulture); } } - + /// /// Looks up a localized string similar to darf nicht leer sein. /// @@ -365,7 +365,7 @@ public static string IsRequired { return ResourceManager.GetString("IsRequired", resourceCulture); } } - + /// /// Looks up a localized string similar to Sprachen. /// @@ -374,7 +374,7 @@ public static string Languages { return ResourceManager.GetString("Languages", resourceCulture); } } - + /// /// Looks up a localized string similar to Lade. /// @@ -383,7 +383,7 @@ public static string Loading { return ResourceManager.GetString("Loading", resourceCulture); } } - + /// /// Looks up a localized string similar to Ort. /// @@ -392,7 +392,7 @@ public static string Location { return ResourceManager.GetString("Location", resourceCulture); } } - + /// /// Looks up a localized string similar to Standardmediaplayer. /// @@ -401,7 +401,7 @@ public static string MainMediaplayer { return ResourceManager.GetString("MainMediaplayer", resourceCulture); } } - + /// /// Looks up a localized string similar to Es können keine weiteren Wiedergabelisten angelegt werden, da die maximale Anzahl erreicht wurde. /// @@ -410,7 +410,7 @@ public static string MaxPlaylistCountReachedException { return ResourceManager.GetString("MaxPlaylistCountReachedException", resourceCulture); } } - + /// /// Looks up a localized string similar to Wiedergabetitel. /// @@ -419,7 +419,7 @@ public static string MediaItem { return ResourceManager.GetString("MediaItem", resourceCulture); } } - + /// /// Looks up a localized string similar to Wiedergabetitel. /// @@ -428,7 +428,7 @@ public static string MediaItems { return ResourceManager.GetString("MediaItems", resourceCulture); } } - + /// /// Looks up a localized string similar to Zur Wiedergabeliste wechseln. /// @@ -437,7 +437,7 @@ public static string MediaPlayerCommand { return ResourceManager.GetString("MediaPlayerCommand", resourceCulture); } } - + /// /// Looks up a localized string similar to Mediaplayers. /// @@ -446,7 +446,7 @@ public static string MediaPlayers { return ResourceManager.GetString("MediaPlayers", resourceCulture); } } - + /// /// Looks up a localized string similar to Navigation wird geladen. /// @@ -455,7 +455,7 @@ public static string NavigationLoad { return ResourceManager.GetString("NavigationLoad", resourceCulture); } } - + /// /// Looks up a localized string similar to Navigation geladen. /// @@ -464,7 +464,7 @@ public static string NavigationLoaded { return ResourceManager.GetString("NavigationLoaded", resourceCulture); } } - + /// /// Looks up a localized string similar to Neu. /// @@ -473,7 +473,7 @@ public static string New { return ResourceManager.GetString("New", resourceCulture); } } - + /// /// Looks up a localized string similar to Weiter. /// @@ -482,7 +482,7 @@ public static string Next { return ResourceManager.GetString("Next", resourceCulture); } } - + /// /// Looks up a localized string similar to Einstellungen. /// @@ -491,7 +491,7 @@ public static string Options { return ResourceManager.GetString("Options", resourceCulture); } } - + /// /// Looks up a localized string similar to Zu den Einstellungen wechseln. /// @@ -500,7 +500,7 @@ public static string OptionsCommand { return ResourceManager.GetString("OptionsCommand", resourceCulture); } } - + /// /// Looks up a localized string similar to Analysieren. /// @@ -509,7 +509,7 @@ public static string Parse { return ResourceManager.GetString("Parse", resourceCulture); } } - + /// /// Looks up a localized string similar to Wiedergabe. /// @@ -518,7 +518,7 @@ public static string Playback { return ResourceManager.GetString("Playback", resourceCulture); } } - + /// /// Looks up a localized string similar to Wiedergabemodus. /// @@ -527,7 +527,7 @@ public static string PlaybackMode { return ResourceManager.GetString("PlaybackMode", resourceCulture); } } - + /// /// Looks up a localized string similar to Alle Titel wiederholen. /// @@ -536,7 +536,7 @@ public static string PlaybackModeAll { return ResourceManager.GetString("PlaybackModeAll", resourceCulture); } } - + /// /// Looks up a localized string similar to Keinen Titel wiederholen. /// @@ -545,7 +545,7 @@ public static string PlaybackModeNone { return ResourceManager.GetString("PlaybackModeNone", resourceCulture); } } - + /// /// Looks up a localized string similar to Einen Titel wiederholen. /// @@ -554,7 +554,7 @@ public static string PlaybackModeOne { return ResourceManager.GetString("PlaybackModeOne", resourceCulture); } } - + /// /// Looks up a localized string similar to Zufällige Wiedergabe. /// @@ -563,7 +563,7 @@ public static string PlaybackShuffle { return ResourceManager.GetString("PlaybackShuffle", resourceCulture); } } - + /// /// Looks up a localized string similar to Wiedergabeliste. /// @@ -572,7 +572,7 @@ public static string Playlist { return ResourceManager.GetString("Playlist", resourceCulture); } } - + /// /// Looks up a localized string similar to Wiedergabeliste hinzufügen. /// @@ -581,7 +581,7 @@ public static string PlaylistAdd { return ResourceManager.GetString("PlaylistAdd", resourceCulture); } } - + /// /// Looks up a localized string similar to Aktuelle Wiedergabeliste. /// @@ -590,7 +590,7 @@ public static string PlaylistCurrent { return ResourceManager.GetString("PlaylistCurrent", resourceCulture); } } - + /// /// Looks up a localized string similar to Wiedergabelisten. /// @@ -599,7 +599,7 @@ public static string Playlists { return ResourceManager.GetString("Playlists", resourceCulture); } } - + /// /// Looks up a localized string similar to Zurück. /// @@ -608,7 +608,7 @@ public static string Previous { return ResourceManager.GetString("Previous", resourceCulture); } } - + /// /// Looks up a localized string similar to Aktualisieren. /// @@ -617,7 +617,7 @@ public static string Refresh { return ResourceManager.GetString("Refresh", resourceCulture); } } - + /// /// Looks up a localized string similar to Entfernen. /// @@ -626,7 +626,7 @@ public static string Remove { return ResourceManager.GetString("Remove", resourceCulture); } } - + /// /// Looks up a localized string similar to Keine Beschränkung. /// @@ -635,7 +635,7 @@ public static string ResctrictionNone { return ResourceManager.GetString("ResctrictionNone", resourceCulture); } } - + /// /// Looks up a localized string similar to Zugriffsbeschränkung. /// @@ -644,7 +644,7 @@ public static string Restriction { return ResourceManager.GetString("Restriction", resourceCulture); } } - + /// /// Looks up a localized string similar to Kein Zugriff. /// @@ -653,7 +653,7 @@ public static string RestrictionRestricted { return ResourceManager.GetString("RestrictionRestricted", resourceCulture); } } - + /// /// Looks up a localized string similar to Änderungen gespeichert. /// @@ -662,7 +662,7 @@ public static string SavedState { return ResourceManager.GetString("SavedState", resourceCulture); } } - + /// /// Looks up a localized string similar to Speichere. /// @@ -671,7 +671,7 @@ public static string Saving { return ResourceManager.GetString("Saving", resourceCulture); } } - + /// /// Looks up a localized string similar to Änderungen werden gespeichert. /// @@ -680,7 +680,7 @@ public static string SavingState { return ResourceManager.GetString("SavingState", resourceCulture); } } - + /// /// Looks up a localized string similar to Auswählen. /// @@ -689,7 +689,7 @@ public static string Select { return ResourceManager.GetString("Select", resourceCulture); } } - + /// /// Looks up a localized string similar to Dateiauswahl. /// @@ -698,7 +698,7 @@ public static string SelectFiles { return ResourceManager.GetString("SelectFiles", resourceCulture); } } - + /// /// Looks up a localized string similar to Ordnerauswahl. /// @@ -707,7 +707,7 @@ public static string SelectFolder { return ResourceManager.GetString("SelectFolder", resourceCulture); } } - + /// /// Looks up a localized string similar to Maple. /// @@ -716,7 +716,7 @@ public static string ShellTitle { return ResourceManager.GetString("ShellTitle", resourceCulture); } } - + /// /// Looks up a localized string similar to Farbprofile. /// @@ -725,7 +725,7 @@ public static string Themes { return ResourceManager.GetString("Themes", resourceCulture); } } - + /// /// Looks up a localized string similar to Titel. /// @@ -734,7 +734,7 @@ public static string Title { return ResourceManager.GetString("Title", resourceCulture); } } - + /// /// Looks up a localized string similar to Video hinzufügen. /// @@ -743,7 +743,7 @@ public static string VideoAdd { return ResourceManager.GetString("VideoAdd", resourceCulture); } } - + /// /// Looks up a localized string similar to Lautstärke. /// @@ -752,7 +752,7 @@ public static string Volume { return ResourceManager.GetString("Volume", resourceCulture); } } - + /// /// Looks up a localized string similar to Youtubeservice wird geladen. /// @@ -761,7 +761,7 @@ public static string YoutubeLoad { return ResourceManager.GetString("YoutubeLoad", resourceCulture); } } - + /// /// Looks up a localized string similar to Youtubeservice geladen. /// @@ -770,7 +770,7 @@ public static string YoutubeLoaded { return ResourceManager.GetString("YoutubeLoaded", resourceCulture); } } - + /// /// Looks up a localized string similar to Eine Widergabeliste von Youtube importieren. /// diff --git a/src/Maple.Core/Interfaces/IConfigurableWindowSettings.cs b/src/Maple/Interfaces/IConfigurableWindowSettings.cs similarity index 94% rename from src/Maple.Core/Interfaces/IConfigurableWindowSettings.cs rename to src/Maple/Interfaces/IConfigurableWindowSettings.cs index bf370d0..7242770 100644 --- a/src/Maple.Core/Interfaces/IConfigurableWindowSettings.cs +++ b/src/Maple/Interfaces/IConfigurableWindowSettings.cs @@ -1,10 +1,7 @@ using System.Windows; -namespace Maple.Core +namespace Maple { - /// - /// - /// public interface IConfigurableWindowSettings { /// diff --git a/src/Maple.Core/Interfaces/IIocFrameworkElement.cs b/src/Maple/Interfaces/IIocFrameworkElement.cs similarity index 100% rename from src/Maple.Core/Interfaces/IIocFrameworkElement.cs rename to src/Maple/Interfaces/IIocFrameworkElement.cs diff --git a/src/Maple/Maple.csproj b/src/Maple/Maple.csproj index c6b270b..0fa81ef 100644 --- a/src/Maple/Maple.csproj +++ b/src/Maple/Maple.csproj @@ -121,6 +121,8 @@ Properties\SharedAssemblyInfo.cs + + @@ -157,7 +159,7 @@ - + diff --git a/src/Maple/Properties/AssemblyInfo.cs b/src/Maple/Properties/AssemblyInfo.cs index 09980fb..277b25e 100644 --- a/src/Maple/Properties/AssemblyInfo.cs +++ b/src/Maple/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ -using System.Runtime.InteropServices; -using System.Reflection; +using System.Reflection; using System.Windows; [assembly: AssemblyTitle("Maple")] diff --git a/src/Maple/UI/Base/ConfigurableWindow.cs b/src/Maple/UI/Base/ConfigurableWindow.cs index 6fac2f1..ccf4a68 100644 --- a/src/Maple/UI/Base/ConfigurableWindow.cs +++ b/src/Maple/UI/Base/ConfigurableWindow.cs @@ -3,7 +3,6 @@ using System.Windows; using System.Windows.Threading; using MahApps.Metro.Controls; -using Maple.Core; namespace Maple { diff --git a/src/Maple/UI/Base/ConfigurableWindowSettings.cs b/src/Maple/UI/Base/ConfigurableWindowSettings.cs index 68a9497..5a352ce 100644 --- a/src/Maple/UI/Base/ConfigurableWindowSettings.cs +++ b/src/Maple/UI/Base/ConfigurableWindowSettings.cs @@ -1,6 +1,5 @@ using System.Configuration; using System.Windows; -using Maple.Core; namespace Maple { diff --git a/src/Maple/UI/UserControls/MediaPlayerPage.xaml.cs b/src/Maple/UI/UserControls/MediaPlayerPage.xaml.cs index 88cc6df..3a0a77f 100644 --- a/src/Maple/UI/UserControls/MediaPlayerPage.xaml.cs +++ b/src/Maple/UI/UserControls/MediaPlayerPage.xaml.cs @@ -1,6 +1,4 @@ -using Maple.Core; - -namespace Maple +namespace Maple { public partial class MediaPlayerPage { diff --git a/src/Maple/UI/UserControls/MediaPlayersPage.xaml.cs b/src/Maple/UI/UserControls/MediaPlayersPage.xaml.cs index 923ef9b..6a4dd8b 100644 --- a/src/Maple/UI/UserControls/MediaPlayersPage.xaml.cs +++ b/src/Maple/UI/UserControls/MediaPlayersPage.xaml.cs @@ -1,6 +1,4 @@ -using Maple.Core; - -namespace Maple +namespace Maple { public partial class MediaPlayersPage { diff --git a/src/Maple/UI/UserControls/Options/ColorOptionsPage.xaml.cs b/src/Maple/UI/UserControls/Options/ColorOptionsPage.xaml.cs index b9937e1..6fe0111 100644 --- a/src/Maple/UI/UserControls/Options/ColorOptionsPage.xaml.cs +++ b/src/Maple/UI/UserControls/Options/ColorOptionsPage.xaml.cs @@ -1,6 +1,4 @@ -using Maple.Core; - -namespace Maple +namespace Maple { public partial class ColorOptionsPage { diff --git a/src/Maple/UI/UserControls/Options/OptionsPage.xaml.cs b/src/Maple/UI/UserControls/Options/OptionsPage.xaml.cs index 3228e2c..abb8903 100644 --- a/src/Maple/UI/UserControls/Options/OptionsPage.xaml.cs +++ b/src/Maple/UI/UserControls/Options/OptionsPage.xaml.cs @@ -1,6 +1,4 @@ -using Maple.Core; - -namespace Maple +namespace Maple { public partial class OptionsPage { diff --git a/src/Maple/UI/UserControls/Playlist/NewPlaylistOptionsPage.xaml.cs b/src/Maple/UI/UserControls/Playlist/NewPlaylistOptionsPage.xaml.cs index 852826c..ef9b3e8 100644 --- a/src/Maple/UI/UserControls/Playlist/NewPlaylistOptionsPage.xaml.cs +++ b/src/Maple/UI/UserControls/Playlist/NewPlaylistOptionsPage.xaml.cs @@ -1,6 +1,4 @@ -using Maple.Core; - -namespace Maple +namespace Maple { public partial class NewPlaylistOptionsPage { diff --git a/src/Maple/UI/UserControls/Playlist/NewPlaylistPage.xaml.cs b/src/Maple/UI/UserControls/Playlist/NewPlaylistPage.xaml.cs index fd9772d..9464c19 100644 --- a/src/Maple/UI/UserControls/Playlist/NewPlaylistPage.xaml.cs +++ b/src/Maple/UI/UserControls/Playlist/NewPlaylistPage.xaml.cs @@ -1,6 +1,4 @@ -using Maple.Core; - -namespace Maple +namespace Maple { public partial class NewPlaylistPage { diff --git a/src/Maple/UI/UserControls/Playlist/PlaylistsPage.xaml.cs b/src/Maple/UI/UserControls/Playlist/PlaylistsPage.xaml.cs index dc83d72..af99f71 100644 --- a/src/Maple/UI/UserControls/Playlist/PlaylistsPage.xaml.cs +++ b/src/Maple/UI/UserControls/Playlist/PlaylistsPage.xaml.cs @@ -1,6 +1,4 @@ -using Maple.Core; - -namespace Maple +namespace Maple { public partial class PlaylistsPage { diff --git a/src/Maple/Utils/Mappers/MapperExtensions.cs b/src/Maple/Utils/Mappers/Base/MapperExtensions.cs similarity index 100% rename from src/Maple/Utils/Mappers/MapperExtensions.cs rename to src/Maple/Utils/Mappers/Base/MapperExtensions.cs diff --git a/src/Maple/Utils/Validation/Base/BaseValidator.cs b/src/Maple/Utils/Validation/Base/BaseValidator.cs index 66d88a9..9da734b 100644 --- a/src/Maple/Utils/Validation/Base/BaseValidator.cs +++ b/src/Maple/Utils/Validation/Base/BaseValidator.cs @@ -1,6 +1,5 @@ using System; using FluentValidation; -using Maple.Core; using Maple.Localization.Properties; namespace Maple diff --git a/src/Maple/Utils/Validation/MediaItemValidator.cs b/src/Maple/Utils/Validation/MediaItemValidator.cs index b744c44..23cd0c7 100644 --- a/src/Maple/Utils/Validation/MediaItemValidator.cs +++ b/src/Maple/Utils/Validation/MediaItemValidator.cs @@ -1,5 +1,4 @@ using FluentValidation; -using Maple.Core; namespace Maple { diff --git a/src/Maple/Utils/Validation/MediaPlayerValidator.cs b/src/Maple/Utils/Validation/MediaPlayerValidator.cs index 764ca08..37d0e07 100644 --- a/src/Maple/Utils/Validation/MediaPlayerValidator.cs +++ b/src/Maple/Utils/Validation/MediaPlayerValidator.cs @@ -1,5 +1,4 @@ using FluentValidation; -using Maple.Core; namespace Maple { diff --git a/src/Maple/Utils/Validation/PlaylistValidator.cs b/src/Maple/Utils/Validation/PlaylistValidator.cs index 490d1a1..667d0de 100644 --- a/src/Maple/Utils/Validation/PlaylistValidator.cs +++ b/src/Maple/Utils/Validation/PlaylistValidator.cs @@ -1,5 +1,4 @@ using FluentValidation; -using Maple.Core; namespace Maple { diff --git a/src/Maple/Utils/Validation/PlaylistsValidator.cs b/src/Maple/Utils/Validation/PlaylistsValidator.cs index 5c3c8af..8edd389 100644 --- a/src/Maple/Utils/Validation/PlaylistsValidator.cs +++ b/src/Maple/Utils/Validation/PlaylistsValidator.cs @@ -1,5 +1,4 @@ using FluentValidation; -using Maple.Core; namespace Maple { diff --git a/src/Maple/ViewModels/Interfaces/IMediaItemsViewModel.cs b/src/Maple/ViewModels/Interfaces/IMediaItemsViewModel.cs index 4d1748d..5244716 100644 --- a/src/Maple/ViewModels/Interfaces/IMediaItemsViewModel.cs +++ b/src/Maple/ViewModels/Interfaces/IMediaItemsViewModel.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Threading.Tasks; using Maple.Core; namespace Maple diff --git a/src/Maple/ViewModels/Navigation/Scenes.cs b/src/Maple/ViewModels/Navigation/Scenes.cs index 2d3292b..cfb4d97 100644 --- a/src/Maple/ViewModels/Navigation/Scenes.cs +++ b/src/Maple/ViewModels/Navigation/Scenes.cs @@ -2,7 +2,6 @@ using System.ComponentModel; using System.Diagnostics; using System.Linq; -using System.Windows.Controls; using System.Windows.Input; using Maple.Core; using Maple.Domain; From 12b8d4a4ab3c3e79c71eff71757dc22efed3d2e2 Mon Sep 17 00:00:00 2001 From: Insire Date: Mon, 8 Jan 2018 19:21:03 +0100 Subject: [PATCH 04/16] even more refactoring --- .../ViewModels/BaseDataListViewModel.cs | 2 +- .../ViewModels/BaseDataViewModel.cs | 2 +- .../ValidableBaseDataListViewModel.cs | 2 +- .../ViewModels/ValidableBaseDataViewModel.cs | 2 +- .../VirtualizationListViewModel.cs | 2 +- .../Virtualization/VirtualizationViewModel.cs | 2 +- .../Base/MaplePlaylistRepository.cs | 2 +- .../{IBaseObject.cs => IBaseModel.cs} | 2 +- .../Interfaces/IMapleRepository.cs | 2 +- src/Maple.Domain/Maple.Domain.csproj | 4 ++-- .../Base/{BaseObject.cs => BaseModel.cs} | 2 +- src/Maple.Domain/Models/MediaItemModel.cs | 2 +- src/Maple.Domain/Models/MediaPlayerModel.cs | 2 +- src/Maple.Domain/Models/PlaylistModel.cs | 2 +- .../{Utils => }/DependencyInjectionFactory.cs | 0 src/Maple/Interfaces/IBaseMapper.cs | 2 +- src/Maple/Maple.csproj | 22 +++++++++---------- .../Mappers/Base/BaseMapper.cs | 0 .../Mappers/Base/MapperExtensions.cs | 0 .../Mappers/MediaItemMapper.cs | 0 .../Mappers/MediaPlayerMapper.cs | 0 .../Mappers/PlaylistMapper.cs | 0 .../Validation/Base/BaseValidator.cs | 0 .../Validation/MediaItemValidator.cs | 0 .../Validation/MediaPlayerValidator.cs | 0 .../Validation/PlaylistValidator.cs | 0 .../Validation/PlaylistsValidator.cs | 0 27 files changed, 27 insertions(+), 27 deletions(-) rename src/Maple.Domain/Interfaces/{IBaseObject.cs => IBaseModel.cs} (89%) rename src/Maple.Domain/Models/Base/{BaseObject.cs => BaseModel.cs} (90%) rename src/Maple/{Utils => }/DependencyInjectionFactory.cs (100%) rename src/Maple/{Utils => Services}/Mappers/Base/BaseMapper.cs (100%) rename src/Maple/{Utils => Services}/Mappers/Base/MapperExtensions.cs (100%) rename src/Maple/{Utils => Services}/Mappers/MediaItemMapper.cs (100%) rename src/Maple/{Utils => Services}/Mappers/MediaPlayerMapper.cs (100%) rename src/Maple/{Utils => Services}/Mappers/PlaylistMapper.cs (100%) rename src/Maple/{Utils => Services}/Validation/Base/BaseValidator.cs (100%) rename src/Maple/{Utils => Services}/Validation/MediaItemValidator.cs (100%) rename src/Maple/{Utils => Services}/Validation/MediaPlayerValidator.cs (100%) rename src/Maple/{Utils => Services}/Validation/PlaylistValidator.cs (100%) rename src/Maple/{Utils => Services}/Validation/PlaylistsValidator.cs (100%) diff --git a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs index dff50b5..b70d382 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs @@ -16,7 +16,7 @@ namespace Maple.Core /// public abstract class BaseDataListViewModel : BaseListViewModel, ILoadableViewModel, ISaveableViewModel where TViewModel : BaseDataViewModel, ISequence - where TModel : class, IBaseObject + where TModel : class, IBaseModel { protected readonly ISequenceService _sequenceProvider; protected readonly ILocalizationService _translationService; diff --git a/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs index 3cf9535..83c49a6 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs @@ -5,7 +5,7 @@ namespace Maple.Core { public abstract class BaseDataViewModel : BaseViewModel - where TModel : class, IBaseObject + where TModel : class, IBaseModel { protected ChangeTracker ChangeTracker { get; } protected bool SkipChangeTracking { get; set; } diff --git a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs index 6478334..aee0ba2 100644 --- a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs @@ -4,7 +4,7 @@ namespace Maple.Core { public abstract class ValidableBaseDataListViewModel : BaseDataListViewModel where TViewModel : BaseDataViewModel, ISequence - where TModel : class, IBaseObject + where TModel : class, IBaseModel { protected ValidableBaseDataListViewModel(ViewModelServiceContainer container) : base(container) diff --git a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs index 39c5606..000abb4 100644 --- a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs @@ -14,7 +14,7 @@ namespace Maple.Core { public abstract class ValidableBaseDataViewModel : BaseDataViewModel, INotifyDataErrorInfo where TViewModel : BaseDataViewModel, ISequence - where TModel : class, IBaseObject + where TModel : class, IBaseModel { protected bool SkipValidation { get; set; } diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs b/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs index 77cbea4..c09e1fd 100644 --- a/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs +++ b/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs @@ -7,7 +7,7 @@ namespace Maple.Core { public abstract class VirtualizationListViewModel : ValidableBaseDataListViewModel, IVirtualizedViewModel, ILoadableViewModel, ISaveableViewModel where TViewModel : BaseDataViewModel, ISequence - where TModel : class, IBaseObject + where TModel : class, IBaseModel { private bool _isLoaded; /// diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs index 131ed3c..417fbbd 100644 --- a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs +++ b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs @@ -6,7 +6,7 @@ namespace Maple.Core { public sealed class VirtualizationViewModel : ObservableObject - where TModel : class, IBaseObject + where TModel : class, IBaseModel { private readonly IDataProvider, TKeyDataType> _dataProvider; diff --git a/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs b/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs index e2e518f..98f42a6 100644 --- a/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs +++ b/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs @@ -9,7 +9,7 @@ namespace Maple.Data { public abstract class MaplePlaylistRepository : IMapleRepository - where TModel : class, IBaseObject + where TModel : class, IBaseModel { public async Task SaveAsync(TModel item) { diff --git a/src/Maple.Domain/Interfaces/IBaseObject.cs b/src/Maple.Domain/Interfaces/IBaseModel.cs similarity index 89% rename from src/Maple.Domain/Interfaces/IBaseObject.cs rename to src/Maple.Domain/Interfaces/IBaseModel.cs index 96459b6..6525c2d 100644 --- a/src/Maple.Domain/Interfaces/IBaseObject.cs +++ b/src/Maple.Domain/Interfaces/IBaseModel.cs @@ -2,7 +2,7 @@ namespace Maple.Domain { - public interface IBaseObject + public interface IBaseModel { string CreatedBy { get; set; } DateTime CreatedOn { get; set; } diff --git a/src/Maple.Domain/Interfaces/IMapleRepository.cs b/src/Maple.Domain/Interfaces/IMapleRepository.cs index aed1a5e..282b0d5 100644 --- a/src/Maple.Domain/Interfaces/IMapleRepository.cs +++ b/src/Maple.Domain/Interfaces/IMapleRepository.cs @@ -4,7 +4,7 @@ namespace Maple.Domain { public interface IMapleRepository - where TModel : class, IBaseObject + where TModel : class, IBaseModel { Task> GetAsync(); Task GetByIdAsync(TKeyDataType Id); diff --git a/src/Maple.Domain/Maple.Domain.csproj b/src/Maple.Domain/Maple.Domain.csproj index df0120f..a574d80 100644 --- a/src/Maple.Domain/Maple.Domain.csproj +++ b/src/Maple.Domain/Maple.Domain.csproj @@ -54,7 +54,7 @@ - + @@ -68,7 +68,7 @@ - + diff --git a/src/Maple.Domain/Models/Base/BaseObject.cs b/src/Maple.Domain/Models/Base/BaseModel.cs similarity index 90% rename from src/Maple.Domain/Models/Base/BaseObject.cs rename to src/Maple.Domain/Models/Base/BaseModel.cs index 3ab65c9..158a91c 100644 --- a/src/Maple.Domain/Models/Base/BaseObject.cs +++ b/src/Maple.Domain/Models/Base/BaseModel.cs @@ -5,7 +5,7 @@ namespace Maple.Domain { - public abstract class BaseObject : IBaseObject + public abstract class BaseModel : IBaseModel { [Key] [Column(Order = 1)] diff --git a/src/Maple.Domain/Models/MediaItemModel.cs b/src/Maple.Domain/Models/MediaItemModel.cs index b34e99e..4a4e455 100644 --- a/src/Maple.Domain/Models/MediaItemModel.cs +++ b/src/Maple.Domain/Models/MediaItemModel.cs @@ -5,7 +5,7 @@ namespace Maple.Domain { [DebuggerDisplay("{Title}, {Sequence}")] - public class MediaItemModel : BaseObject + public class MediaItemModel : BaseModel { public int PlaylistId { get; set; } [ForeignKey(nameof(PlaylistId))] diff --git a/src/Maple.Domain/Models/MediaPlayerModel.cs b/src/Maple.Domain/Models/MediaPlayerModel.cs index 418f223..1dc9b67 100644 --- a/src/Maple.Domain/Models/MediaPlayerModel.cs +++ b/src/Maple.Domain/Models/MediaPlayerModel.cs @@ -5,7 +5,7 @@ namespace Maple.Domain { [DebuggerDisplay("{Name}, {DeviceName}, {Sequence}")] - public class MediaPlayerModel : BaseObject + public class MediaPlayerModel : BaseModel { public int PlaylistId { get; set; } [ForeignKey(nameof(PlaylistId))] diff --git a/src/Maple.Domain/Models/PlaylistModel.cs b/src/Maple.Domain/Models/PlaylistModel.cs index d03b50e..df04ac2 100644 --- a/src/Maple.Domain/Models/PlaylistModel.cs +++ b/src/Maple.Domain/Models/PlaylistModel.cs @@ -7,7 +7,7 @@ namespace Maple.Domain // tutorial http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx [DebuggerDisplay("{Title}, {SelectedItem}, {Sequence}")] - public class PlaylistModel : BaseObject + public class PlaylistModel : BaseModel { private ICollection _mediaItems; public virtual ICollection MediaItems diff --git a/src/Maple/Utils/DependencyInjectionFactory.cs b/src/Maple/DependencyInjectionFactory.cs similarity index 100% rename from src/Maple/Utils/DependencyInjectionFactory.cs rename to src/Maple/DependencyInjectionFactory.cs diff --git a/src/Maple/Interfaces/IBaseMapper.cs b/src/Maple/Interfaces/IBaseMapper.cs index ed5d02b..8ef2edb 100644 --- a/src/Maple/Interfaces/IBaseMapper.cs +++ b/src/Maple/Interfaces/IBaseMapper.cs @@ -5,7 +5,7 @@ namespace Maple { public interface IBaseMapper where TVieModel : BaseDataViewModel - where TDataModel : class, IBaseObject + where TDataModel : class, IBaseModel { TVieModel Get(TDataModel model); diff --git a/src/Maple/Maple.csproj b/src/Maple/Maple.csproj index 0fa81ef..b9be91f 100644 --- a/src/Maple/Maple.csproj +++ b/src/Maple/Maple.csproj @@ -158,22 +158,22 @@ - - - - - - + + + + + + - - - - - + + + + + diff --git a/src/Maple/Utils/Mappers/Base/BaseMapper.cs b/src/Maple/Services/Mappers/Base/BaseMapper.cs similarity index 100% rename from src/Maple/Utils/Mappers/Base/BaseMapper.cs rename to src/Maple/Services/Mappers/Base/BaseMapper.cs diff --git a/src/Maple/Utils/Mappers/Base/MapperExtensions.cs b/src/Maple/Services/Mappers/Base/MapperExtensions.cs similarity index 100% rename from src/Maple/Utils/Mappers/Base/MapperExtensions.cs rename to src/Maple/Services/Mappers/Base/MapperExtensions.cs diff --git a/src/Maple/Utils/Mappers/MediaItemMapper.cs b/src/Maple/Services/Mappers/MediaItemMapper.cs similarity index 100% rename from src/Maple/Utils/Mappers/MediaItemMapper.cs rename to src/Maple/Services/Mappers/MediaItemMapper.cs diff --git a/src/Maple/Utils/Mappers/MediaPlayerMapper.cs b/src/Maple/Services/Mappers/MediaPlayerMapper.cs similarity index 100% rename from src/Maple/Utils/Mappers/MediaPlayerMapper.cs rename to src/Maple/Services/Mappers/MediaPlayerMapper.cs diff --git a/src/Maple/Utils/Mappers/PlaylistMapper.cs b/src/Maple/Services/Mappers/PlaylistMapper.cs similarity index 100% rename from src/Maple/Utils/Mappers/PlaylistMapper.cs rename to src/Maple/Services/Mappers/PlaylistMapper.cs diff --git a/src/Maple/Utils/Validation/Base/BaseValidator.cs b/src/Maple/Services/Validation/Base/BaseValidator.cs similarity index 100% rename from src/Maple/Utils/Validation/Base/BaseValidator.cs rename to src/Maple/Services/Validation/Base/BaseValidator.cs diff --git a/src/Maple/Utils/Validation/MediaItemValidator.cs b/src/Maple/Services/Validation/MediaItemValidator.cs similarity index 100% rename from src/Maple/Utils/Validation/MediaItemValidator.cs rename to src/Maple/Services/Validation/MediaItemValidator.cs diff --git a/src/Maple/Utils/Validation/MediaPlayerValidator.cs b/src/Maple/Services/Validation/MediaPlayerValidator.cs similarity index 100% rename from src/Maple/Utils/Validation/MediaPlayerValidator.cs rename to src/Maple/Services/Validation/MediaPlayerValidator.cs diff --git a/src/Maple/Utils/Validation/PlaylistValidator.cs b/src/Maple/Services/Validation/PlaylistValidator.cs similarity index 100% rename from src/Maple/Utils/Validation/PlaylistValidator.cs rename to src/Maple/Services/Validation/PlaylistValidator.cs diff --git a/src/Maple/Utils/Validation/PlaylistsValidator.cs b/src/Maple/Services/Validation/PlaylistsValidator.cs similarity index 100% rename from src/Maple/Utils/Validation/PlaylistsValidator.cs rename to src/Maple/Services/Validation/PlaylistsValidator.cs From 05e3ee45ec4a469ad26df675dfb0e1f6994974dd Mon Sep 17 00:00:00 2001 From: Insire Date: Mon, 8 Jan 2018 19:49:35 +0100 Subject: [PATCH 05/16] refactored some testcases, abstracted PlaybackDeviceFactory --- .../ViewModels/BaseListViewModel.cs | 2 + .../DependencyInjectionFactoryTests.cs | 11 +++--- .../TestUtils/ContainerContextExtensions.cs | 38 +++++++++++++++++++ .../ViewModels/Playlists/PlaylistTests.cs | 36 ++++++++++++++++++ .../ViewModels/Playlists/PlaylistsTests.cs | 5 +++ src/Maple/DependencyInjectionFactory.cs | 1 + src/Maple/Maple.csproj | 1 + .../ViewModels/MediaPlayer/AudioDevices.cs | 8 +--- .../NAudio/IPlaybackDeviceFactory.cs | 10 +++++ .../NAudio/PlaybackDeviceFactory.cs | 6 +-- 10 files changed, 103 insertions(+), 15 deletions(-) create mode 100644 src/Maple/ViewModels/MediaPlayer/NAudio/IPlaybackDeviceFactory.cs diff --git a/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs index 45b97e7..b424f79 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs @@ -79,6 +79,8 @@ public TViewModel this[int index] protected BaseListViewModel(IMessenger messenger) : base(messenger) { + _items = new RangeObservableCollection(); + RemoveCommand = new RelayCommand(Remove, CanRemove); RemoveRangeCommand = new RelayCommand(RemoveRange, CanRemoveRange); ClearCommand = new RelayCommand(() => Clear(), CanClear); diff --git a/src/Maple.Test/DependencyInjectionFactoryTests.cs b/src/Maple.Test/DependencyInjectionFactoryTests.cs index a168d9c..e0891af 100644 --- a/src/Maple.Test/DependencyInjectionFactoryTests.cs +++ b/src/Maple.Test/DependencyInjectionFactoryTests.cs @@ -16,6 +16,8 @@ public sealed class DependencyInjectionFactoryTests public async Task SanityMapleGetContainerTest() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); + container.VerifyResolutions(); } @@ -23,6 +25,7 @@ public async Task SanityMapleGetContainerTest() public async Task ResolveMessengerTest() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var messenger = Substitute.For(); container.UseInstance(typeof(IMessenger), messenger, IfAlreadyRegistered: IfAlreadyRegistered.Replace); @@ -34,9 +37,7 @@ public async Task ResolveMessengerTest() public async Task ResolveLoadablesAsList() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); - - var factory = Substitute.For(); - container.UseInstance(factory); + container = container.ConfigureForTesting(); var loadables = container.Resolve>(); @@ -48,9 +49,7 @@ public async Task ResolveLoadablesAsList() public async Task ResolveManyLoadablesAsList() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); - - var factory = Substitute.For(); - container.UseInstance(factory); + container = container.ConfigureForTesting(); var loadables = container.ResolveMany().ToList(); diff --git a/src/Maple.Test/TestUtils/ContainerContextExtensions.cs b/src/Maple.Test/TestUtils/ContainerContextExtensions.cs index 283d43c..588d474 100644 --- a/src/Maple.Test/TestUtils/ContainerContextExtensions.cs +++ b/src/Maple.Test/TestUtils/ContainerContextExtensions.cs @@ -7,6 +7,14 @@ namespace Maple.Test { public static class ContainerContextExtensions { + public static IContainer ConfigureForTesting(this IContainer container) + { + container.UseInstance(CreatePlaybackDeviceFactory()); + container.UseInstance(CreateWavePlayerFactory()); + + return container; + } + public static Playlists CreatePlaylists(this IContainer container) { return new Playlists(container.CreateViewModelServiceContainer(), container.Resolve(), () => container.Resolve()); @@ -29,6 +37,36 @@ public static MediaItem CreateMediaItem(this IContainer container, MediaItemMode return mapper.Get(model); } + public static IPlaybackDeviceFactory CreatePlaybackDeviceFactory() + { + var factory = Substitute.For(); + + factory.GetAudioDevices(default(ILoggingService)).ReturnsForAnyArgs( + new[] + { + new AudioDevice() + { + Channels= 2, + IsSelected = true, + Name = "TestDevice", + Sequence = 1, + } + }); + + return factory; + } + + // should not be used as default replacement in the container, since some tests rely on the messenger relaying message in the class to be tested + public static IMessenger CreateMessenger() + { + return Substitute.For(); + } + + public static IWavePlayerFactory CreateWavePlayerFactory() + { + return Substitute.For(); + } + public static ISequenceService CreateSequenceService() { return Substitute.For(); diff --git a/src/Maple.Test/ViewModels/Playlists/PlaylistTests.cs b/src/Maple.Test/ViewModels/Playlists/PlaylistTests.cs index a031355..94439bd 100644 --- a/src/Maple.Test/ViewModels/Playlists/PlaylistTests.cs +++ b/src/Maple.Test/ViewModels/Playlists/PlaylistTests.cs @@ -31,6 +31,7 @@ public static void ClassInitialize(TestContext context) public async Task Playlist_ShouldRunConstructorWithoutErrors() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var model = _context.CreateModelPlaylist(); var playlist = container.CreatePlaylist(model); @@ -65,6 +66,7 @@ public async Task Playlist_ShouldRunConstructorWithoutErrors() public async Task Playlist_ShouldThrowForEmptyModel() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); Assert.ThrowsException(() => container.CreatePlaylist(default(PlaylistModel))); } @@ -72,6 +74,7 @@ public async Task Playlist_ShouldThrowForEmptyModel() public async Task Playlist_ShouldThrowForEmptyContainer() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); Assert.ThrowsException(() => new Playlist(null, container.Resolve>(), container.Resolve(), container.Resolve(), _context.CreateModelPlaylist())); } @@ -79,6 +82,7 @@ public async Task Playlist_ShouldThrowForEmptyContainer() public async Task Playlist_ShouldThrowForEmptyValidator() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); Assert.ThrowsException(() => new Playlist(container.Resolve(), null, container.Resolve(), container.Resolve(), _context.CreateModelPlaylist())); } @@ -86,6 +90,7 @@ public async Task Playlist_ShouldThrowForEmptyValidator() public async Task Playlist_ShouldThrowForEmptyViewModel() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); Assert.ThrowsException(() => new Playlist(container.Resolve(), container.Resolve>(), null, container.Resolve(), _context.CreateModelPlaylist())); } @@ -93,6 +98,7 @@ public async Task Playlist_ShouldThrowForEmptyViewModel() public async Task Playlist_ShouldThrowForEmptyMediaItemMapper() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); Assert.ThrowsException(() => new Playlist(container.Resolve(), container.Resolve>(), container.Resolve(), null, _context.CreateModelPlaylist())); } @@ -100,6 +106,7 @@ public async Task Playlist_ShouldThrowForEmptyMediaItemMapper() public async Task Playlist_ShouldRunClear() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); Assert.AreEqual(4, playlist.Count); @@ -113,6 +120,7 @@ public async Task Playlist_ShouldRunClear() public async Task Playlist_ShouldAdd() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var mediaItem = container.CreateMediaItem(_context.CreateModelMediaItem()); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); @@ -127,6 +135,7 @@ public async Task Playlist_ShouldAdd() public async Task Playlist_ShouldThrowAddForNull() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); Assert.ThrowsException(() => playlist.Add(null)); @@ -136,6 +145,7 @@ public async Task Playlist_ShouldThrowAddForNull() public async Task Playlist_ShouldAddRange() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var mediaItems = new[] { container.CreateMediaItem(_context.CreateModelMediaItem()), @@ -155,6 +165,7 @@ public async Task Playlist_ShouldAddRange() public async Task Playlist_ShouldHandleAddRangeForEmptyCollection() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var mediaItems = new List(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); @@ -169,6 +180,7 @@ public async Task Playlist_ShouldHandleAddRangeForEmptyCollection() public async Task Playlist_ShouldThrowAddRangeForNull() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); Assert.AreEqual(4, playlist.Count); @@ -180,6 +192,7 @@ public async Task Playlist_ShouldThrowAddRangeForNull() public async Task Playlist_ShouldHandleAddRangeForDuplicateEntries() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var mediaItem = container.CreateMediaItem(_context.CreateModelMediaItem()); var mediaItems = new[] { @@ -200,6 +213,7 @@ public async Task Playlist_ShouldHandleAddRangeForDuplicateEntries() public async Task Playlist_ShouldRemove() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); Assert.AreEqual(4, playlist.Count); @@ -213,6 +227,7 @@ public async Task Playlist_ShouldRemove() public async Task Playlist_ShouldThrowRemoveForNull() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); Assert.ThrowsException(() => playlist.Remove(null)); @@ -222,6 +237,7 @@ public async Task Playlist_ShouldThrowRemoveForNull() public async Task Playlist_ShouldRemoveRange() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); var mediaItems = new[] { @@ -241,6 +257,7 @@ public async Task Playlist_ShouldRemoveRange() public async Task Playlist_ShouldThrowRemoveRangeForNull() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); Assert.ThrowsException(() => playlist.RemoveRange(null)); @@ -250,6 +267,7 @@ public async Task Playlist_ShouldThrowRemoveRangeForNull() public async Task Playlist_ShouldHandleRemoveRangeForSameItem() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); var mediaItems = new[] { @@ -269,6 +287,7 @@ public async Task Playlist_ShouldHandleRemoveRangeForSameItem() public async Task Playlist_ShouldHandleRemoveRangeForUnknownItem() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); var mediaItems = new List() { @@ -286,6 +305,7 @@ public async Task Playlist_ShouldHandleRemoveRangeForUnknownItem() public async Task Playlist_ShouldHandleRemoveRangeForUnknownItems() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); var mediaItems = new[] { @@ -305,6 +325,7 @@ public async Task Playlist_ShouldHandleRemoveRangeForUnknownItems() public async Task Playlist_ShouldHandleRemoveRangeForEmptyCollection() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); var mediaItems = new List(); @@ -319,6 +340,7 @@ public async Task Playlist_ShouldHandleRemoveRangeForEmptyCollection() public async Task Playlist_ShouldRunNext() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); playlist.RepeatMode = RepeatMode.None; var mediaItem = playlist.Next(); @@ -332,6 +354,7 @@ public async Task Playlist_ShouldRunNext() public async Task Playlist_ShouldRunNextWithRepeatModeNone() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); playlist.RepeatMode = RepeatMode.None; playlist.SelectedItem = playlist[3]; @@ -345,6 +368,7 @@ public async Task Playlist_ShouldRunNextWithRepeatModeNone() public async Task Playlist_ShouldRunNextWithRepeatModeAll() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); playlist.RepeatMode = RepeatMode.All; playlist.SelectedItem = playlist[3]; @@ -359,6 +383,7 @@ public async Task Playlist_ShouldRunNextWithRepeatModeAll() public async Task Playlist_ShouldRunNextWithRepeatModeAllWhileShuffeling() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); playlist.RepeatMode = RepeatMode.All; playlist.IsShuffeling = true; @@ -374,6 +399,7 @@ public async Task Playlist_ShouldRunNextWithRepeatModeAllWhileShuffeling() public async Task Playlist_ShouldRunNextWithRepeatModeNoneWhileShuffeling() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); playlist.RepeatMode = RepeatMode.None; playlist.IsShuffeling = true; @@ -389,6 +415,7 @@ public async Task Playlist_ShouldRunNextWithRepeatModeNoneWhileShuffeling() public async Task Playlist_ShouldRunNextWithRepeatModeSingleWhileShuffeling() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); playlist.RepeatMode = RepeatMode.Single; playlist.IsShuffeling = true; @@ -404,6 +431,7 @@ public async Task Playlist_ShouldRunNextWithRepeatModeSingleWhileShuffeling() public async Task Playlist_ShouldRunNextWithRepeatModeSingle() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); playlist.RepeatMode = RepeatMode.Single; @@ -418,6 +446,7 @@ public async Task Playlist_ShouldRunNextWithRepeatModeSingle() public async Task Playlist_ShouldRunPrevious() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); var messenger = container.Resolve(); @@ -453,6 +482,7 @@ public async Task Playlist_ShouldRunPrevious() public async Task Playlist_ShouldRaiseSelectionChanging() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var messenger = Substitute.For(); container.UseInstance(typeof(IMessenger), messenger, IfAlreadyRegistered: IfAlreadyRegistered.Replace); @@ -470,6 +500,7 @@ public async Task Playlist_ShouldRaiseSelectionChanging() public async Task Playlist_ShouldRaiseSelectionChanged() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var messenger = Substitute.For(); container.UseInstance(typeof(IMessenger), messenger, IfAlreadyRegistered: IfAlreadyRegistered.Replace); @@ -487,6 +518,7 @@ public async Task Playlist_ShouldRaiseSelectionChanged() public async Task Playlist_ShouldSynchronizeItemsWithModelWhenRemovingSelectedItem() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var model = _context.CreateModelPlaylist(); var playlist = container.CreatePlaylist(model); var selectedModel = playlist.SelectedItem.Model; @@ -505,6 +537,7 @@ public async Task Playlist_ShouldSynchronizeItemsWithModelWhenRemovingSelectedIt public async Task Playlist_ShouldSynchronizeItemsWithModelWhenRemoving() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var model = _context.CreateModelPlaylist(); var playlist = container.CreatePlaylist(model); var mediaItem1 = playlist[1]; @@ -530,6 +563,7 @@ public async Task Playlist_ShouldAddItemsFromFileDialog() { var tokenSource = new CancellationTokenSource(1000); var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var mediaItems = new[] { container.CreateMediaItem(new MediaItemModel()), @@ -556,6 +590,7 @@ public async Task Playlist_ShouldAddItemsFromFolderDialog() { var tokenSource = new CancellationTokenSource(1000); var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var mediaItems = new[] { container.CreateMediaItem(new MediaItemModel()), @@ -582,6 +617,7 @@ public async Task Playlist_ShouldAddItemsFromUrlDialog() { var tokenSource = new CancellationTokenSource(1000); var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var mediaItems = new[] { container.CreateMediaItem(new MediaItemModel()), diff --git a/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs b/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs index 06a4acb..1a44f6c 100644 --- a/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs +++ b/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs @@ -23,6 +23,7 @@ public static void ClassInitialize(TestContext context) public async Task Playlists_ShouldRunConstructorWithErrors() { var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); + container = container.ConfigureForTesting(); var playlists = container.CreatePlaylists(); @@ -49,6 +50,7 @@ public async Task Playlists_ShouldAdd() var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); var sequenceProvider = ContainerContextExtensions.CreateSequenceService(); sequenceProvider.Get(default(List)).ReturnsForAnyArgs(5); + container = container.ConfigureForTesting(); container.UseInstance(sequenceProvider); var playlists = (Playlists)container.Resolve(); @@ -70,6 +72,7 @@ public async Task Playlists_ShouldAddWithExplicitValue() var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); var sequenceProvider = ContainerContextExtensions.CreateSequenceService(); sequenceProvider.Get(default(List)).ReturnsForAnyArgs(5); + container = container.ConfigureForTesting(); container.UseInstance(sequenceProvider); var playlist = container.CreatePlaylist(_context.CreateModelPlaylist()); @@ -93,6 +96,7 @@ public async Task Playlists_ShouldSave() var container = await DependencyInjectionFactory.Get().ConfigureAwait(false); var repository = ContainerContextExtensions.CreateRepository(); + container = container.ConfigureForTesting(); container.UseInstance(repository); var playlists = container.Resolve(); @@ -114,6 +118,7 @@ public async Task Playlists_ShouldLoad() }; var repository = ContainerContextExtensions.CreateRepository(); repository.GetPlaylistsAsync().ReturnsForAnyArgs(dummyPlaylists); + container = container.ConfigureForTesting(); container.UseInstance(repository); var playlists = (Playlists)container.Resolve(); diff --git a/src/Maple/DependencyInjectionFactory.cs b/src/Maple/DependencyInjectionFactory.cs index ea11807..dc22a04 100644 --- a/src/Maple/DependencyInjectionFactory.cs +++ b/src/Maple/DependencyInjectionFactory.cs @@ -66,6 +66,7 @@ void RegisterServices() c.Register(setup: Setup.With(allowDisposableTransient: true)); c.Register(Reuse.Singleton); c.Register(Reuse.Singleton, setup: Setup.With(allowDisposableTransient: true)); + c.Register(Reuse.Singleton); c.Register(Reuse.Singleton); c.Register(Reuse.Transient, setup: Setup.With(allowDisposableTransient: true)); diff --git a/src/Maple/Maple.csproj b/src/Maple/Maple.csproj index b9be91f..7252149 100644 --- a/src/Maple/Maple.csproj +++ b/src/Maple/Maple.csproj @@ -192,6 +192,7 @@ + diff --git a/src/Maple/ViewModels/MediaPlayer/AudioDevices.cs b/src/Maple/ViewModels/MediaPlayer/AudioDevices.cs index 03afdf9..d3d6fe6 100644 --- a/src/Maple/ViewModels/MediaPlayer/AudioDevices.cs +++ b/src/Maple/ViewModels/MediaPlayer/AudioDevices.cs @@ -4,16 +4,12 @@ namespace Maple { - /// - /// - /// - /// public class AudioDevices : BaseListViewModel { - public AudioDevices(ILoggingService log, IMessenger messenger) + public AudioDevices(ILoggingService log, IMessenger messenger, IPlaybackDeviceFactory factory) : base(messenger) { - AddRange(PlaybackDeviceFactory.GetAudioDevices(log).ToList()); + AddRange(factory.GetAudioDevices(log).ToList()); } } } diff --git a/src/Maple/ViewModels/MediaPlayer/NAudio/IPlaybackDeviceFactory.cs b/src/Maple/ViewModels/MediaPlayer/NAudio/IPlaybackDeviceFactory.cs new file mode 100644 index 0000000..375e7d8 --- /dev/null +++ b/src/Maple/ViewModels/MediaPlayer/NAudio/IPlaybackDeviceFactory.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using Maple.Domain; + +namespace Maple +{ + public interface IPlaybackDeviceFactory + { + IEnumerable GetAudioDevices(ILoggingService log); + } +} \ No newline at end of file diff --git a/src/Maple/ViewModels/MediaPlayer/NAudio/PlaybackDeviceFactory.cs b/src/Maple/ViewModels/MediaPlayer/NAudio/PlaybackDeviceFactory.cs index 6546fd2..424e3e1 100644 --- a/src/Maple/ViewModels/MediaPlayer/NAudio/PlaybackDeviceFactory.cs +++ b/src/Maple/ViewModels/MediaPlayer/NAudio/PlaybackDeviceFactory.cs @@ -5,9 +5,9 @@ namespace Maple { - public static class PlaybackDeviceFactory + public class PlaybackDeviceFactory : IPlaybackDeviceFactory { - public static IEnumerable GetAudioDevices(ILoggingService log) + public IEnumerable GetAudioDevices(ILoggingService log) { for (var i = 0; i < WaveOut.DeviceCount; i++) { @@ -25,7 +25,7 @@ public static IEnumerable GetAudioDevices(ILoggingService log) } - private static WaveOutCapabilities GetCapabilities(int index, ILoggingService log) + private WaveOutCapabilities GetCapabilities(int index, ILoggingService log) { try { From e26ac22201594f9091257a6441ca91cae1aaf3d0 Mon Sep 17 00:00:00 2001 From: Insire Date: Mon, 8 Jan 2018 20:09:43 +0100 Subject: [PATCH 06/16] refactored stuff again, preparations for implementing a weakreference cache --- .../EventAggregator/MapleMessenger.cs | 4 +-- .../CancellableGenericMapleMessage.cs | 0 .../{ => Base}/GenericMapleMessage.cs | 0 .../Messages/{ => Base}/MapleMessageBase.cs | 0 .../Messages/CompletedMediaItemMessage.cs | 0 .../Messages/FileSystemInfoChangedMessage.cs | 0 .../Messages/LoadedMessage.cs | 0 .../Messages/LogMessageReceivedMessage.cs | 0 .../Messages/PlayingMediaItemMessage.cs | 0 .../Messages/RepeatModeChangedMessage.cs | 0 .../Messages/ShuffleModeChangedMessage.cs | 0 .../Messages/UiPrimaryColorChangedMessage.cs | 0 .../ViewModelSelectionChangedMessage.cs | 0 .../ViewModelSelectionChangingMessage.cs | 0 .../EventAggregator/SubscriptionToken.cs | 2 +- src/Maple.Core/Maple.Core.csproj | 28 +++++++++---------- .../Virtualization/VirtualizationViewModel.cs | 6 ++-- ...Service.cs => SimpleStaticCacheService.cs} | 2 +- .../Services/Caching/WeakReferenceCache.cs | 12 ++++++-- 19 files changed, 31 insertions(+), 23 deletions(-) rename src/Maple.Core/EventAggregator/Messages/{ => Base}/CancellableGenericMapleMessage.cs (100%) rename src/Maple.Core/EventAggregator/Messages/{ => Base}/GenericMapleMessage.cs (100%) rename src/Maple.Core/EventAggregator/Messages/{ => Base}/MapleMessageBase.cs (100%) rename src/Maple.Core/{ => EventAggregator}/Messages/CompletedMediaItemMessage.cs (100%) rename src/Maple.Core/{ => EventAggregator}/Messages/FileSystemInfoChangedMessage.cs (100%) rename src/Maple.Core/{ => EventAggregator}/Messages/LoadedMessage.cs (100%) rename src/Maple.Core/{ => EventAggregator}/Messages/LogMessageReceivedMessage.cs (100%) rename src/Maple.Core/{ => EventAggregator}/Messages/PlayingMediaItemMessage.cs (100%) rename src/Maple.Core/{ => EventAggregator}/Messages/RepeatModeChangedMessage.cs (100%) rename src/Maple.Core/{ => EventAggregator}/Messages/ShuffleModeChangedMessage.cs (100%) rename src/Maple.Core/{ => EventAggregator}/Messages/UiPrimaryColorChangedMessage.cs (100%) rename src/Maple.Core/{ => EventAggregator}/Messages/ViewModelSelectionChangedMessage.cs (100%) rename src/Maple.Core/{ => EventAggregator}/Messages/ViewModelSelectionChangingMessage.cs (100%) rename src/Maple.Core/Services/Caching/{SimpleInMemoryCacheService.cs => SimpleStaticCacheService.cs} (68%) diff --git a/src/Maple.Core/EventAggregator/MapleMessenger.cs b/src/Maple.Core/EventAggregator/MapleMessenger.cs index c00fd6c..661b76b 100644 --- a/src/Maple.Core/EventAggregator/MapleMessenger.cs +++ b/src/Maple.Core/EventAggregator/MapleMessenger.cs @@ -25,13 +25,13 @@ public MapleMessenger(ITranslationProvider translationProvider, ILoggingService public SubscriptionToken Subscribe(Action deliveryAction) where TMessage : class, IMapleMessage { - return AddSubscriptionInternal(deliveryAction, (m) => true, true, _mapleMessageProxy); + return AddSubscriptionInternal(deliveryAction, (m) => true, false, _mapleMessageProxy); } public SubscriptionToken Subscribe(Action deliveryAction, IMapleMessageProxy proxy) where TMessage : class, IMapleMessage { - return AddSubscriptionInternal(deliveryAction, (m) => true, true, proxy); + return AddSubscriptionInternal(deliveryAction, (m) => true, false, proxy); } public SubscriptionToken Subscribe(Action deliveryAction, bool useStrongReferences) diff --git a/src/Maple.Core/EventAggregator/Messages/CancellableGenericMapleMessage.cs b/src/Maple.Core/EventAggregator/Messages/Base/CancellableGenericMapleMessage.cs similarity index 100% rename from src/Maple.Core/EventAggregator/Messages/CancellableGenericMapleMessage.cs rename to src/Maple.Core/EventAggregator/Messages/Base/CancellableGenericMapleMessage.cs diff --git a/src/Maple.Core/EventAggregator/Messages/GenericMapleMessage.cs b/src/Maple.Core/EventAggregator/Messages/Base/GenericMapleMessage.cs similarity index 100% rename from src/Maple.Core/EventAggregator/Messages/GenericMapleMessage.cs rename to src/Maple.Core/EventAggregator/Messages/Base/GenericMapleMessage.cs diff --git a/src/Maple.Core/EventAggregator/Messages/MapleMessageBase.cs b/src/Maple.Core/EventAggregator/Messages/Base/MapleMessageBase.cs similarity index 100% rename from src/Maple.Core/EventAggregator/Messages/MapleMessageBase.cs rename to src/Maple.Core/EventAggregator/Messages/Base/MapleMessageBase.cs diff --git a/src/Maple.Core/Messages/CompletedMediaItemMessage.cs b/src/Maple.Core/EventAggregator/Messages/CompletedMediaItemMessage.cs similarity index 100% rename from src/Maple.Core/Messages/CompletedMediaItemMessage.cs rename to src/Maple.Core/EventAggregator/Messages/CompletedMediaItemMessage.cs diff --git a/src/Maple.Core/Messages/FileSystemInfoChangedMessage.cs b/src/Maple.Core/EventAggregator/Messages/FileSystemInfoChangedMessage.cs similarity index 100% rename from src/Maple.Core/Messages/FileSystemInfoChangedMessage.cs rename to src/Maple.Core/EventAggregator/Messages/FileSystemInfoChangedMessage.cs diff --git a/src/Maple.Core/Messages/LoadedMessage.cs b/src/Maple.Core/EventAggregator/Messages/LoadedMessage.cs similarity index 100% rename from src/Maple.Core/Messages/LoadedMessage.cs rename to src/Maple.Core/EventAggregator/Messages/LoadedMessage.cs diff --git a/src/Maple.Core/Messages/LogMessageReceivedMessage.cs b/src/Maple.Core/EventAggregator/Messages/LogMessageReceivedMessage.cs similarity index 100% rename from src/Maple.Core/Messages/LogMessageReceivedMessage.cs rename to src/Maple.Core/EventAggregator/Messages/LogMessageReceivedMessage.cs diff --git a/src/Maple.Core/Messages/PlayingMediaItemMessage.cs b/src/Maple.Core/EventAggregator/Messages/PlayingMediaItemMessage.cs similarity index 100% rename from src/Maple.Core/Messages/PlayingMediaItemMessage.cs rename to src/Maple.Core/EventAggregator/Messages/PlayingMediaItemMessage.cs diff --git a/src/Maple.Core/Messages/RepeatModeChangedMessage.cs b/src/Maple.Core/EventAggregator/Messages/RepeatModeChangedMessage.cs similarity index 100% rename from src/Maple.Core/Messages/RepeatModeChangedMessage.cs rename to src/Maple.Core/EventAggregator/Messages/RepeatModeChangedMessage.cs diff --git a/src/Maple.Core/Messages/ShuffleModeChangedMessage.cs b/src/Maple.Core/EventAggregator/Messages/ShuffleModeChangedMessage.cs similarity index 100% rename from src/Maple.Core/Messages/ShuffleModeChangedMessage.cs rename to src/Maple.Core/EventAggregator/Messages/ShuffleModeChangedMessage.cs diff --git a/src/Maple.Core/Messages/UiPrimaryColorChangedMessage.cs b/src/Maple.Core/EventAggregator/Messages/UiPrimaryColorChangedMessage.cs similarity index 100% rename from src/Maple.Core/Messages/UiPrimaryColorChangedMessage.cs rename to src/Maple.Core/EventAggregator/Messages/UiPrimaryColorChangedMessage.cs diff --git a/src/Maple.Core/Messages/ViewModelSelectionChangedMessage.cs b/src/Maple.Core/EventAggregator/Messages/ViewModelSelectionChangedMessage.cs similarity index 100% rename from src/Maple.Core/Messages/ViewModelSelectionChangedMessage.cs rename to src/Maple.Core/EventAggregator/Messages/ViewModelSelectionChangedMessage.cs diff --git a/src/Maple.Core/Messages/ViewModelSelectionChangingMessage.cs b/src/Maple.Core/EventAggregator/Messages/ViewModelSelectionChangingMessage.cs similarity index 100% rename from src/Maple.Core/Messages/ViewModelSelectionChangingMessage.cs rename to src/Maple.Core/EventAggregator/Messages/ViewModelSelectionChangingMessage.cs diff --git a/src/Maple.Core/EventAggregator/SubscriptionToken.cs b/src/Maple.Core/EventAggregator/SubscriptionToken.cs index 5eaaf0b..b4b474b 100644 --- a/src/Maple.Core/EventAggregator/SubscriptionToken.cs +++ b/src/Maple.Core/EventAggregator/SubscriptionToken.cs @@ -35,7 +35,7 @@ private void Dispose(bool disposing) // free managed resources if (_hub.IsAlive && _hub.Target is IMessenger hub) { - var unsubscribeMethod = typeof(IMessenger).GetMethod("Unsubscribe", new Type[] { typeof(SubscriptionToken) }); + var unsubscribeMethod = typeof(IMessenger).GetMethod(nameof(IMessenger.Unsubscribe), new Type[] { typeof(SubscriptionToken) }); unsubscribeMethod = unsubscribeMethod.MakeGenericMethod(_messageType); unsubscribeMethod.Invoke(hub, new object[] { this }); } diff --git a/src/Maple.Core/Maple.Core.csproj b/src/Maple.Core/Maple.Core.csproj index aeb7c04..4023e76 100644 --- a/src/Maple.Core/Maple.Core.csproj +++ b/src/Maple.Core/Maple.Core.csproj @@ -91,22 +91,23 @@ - - - + + + - - - - - + + + + + - + + @@ -117,10 +118,10 @@ - - - - + + + + @@ -173,7 +174,6 @@ - diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs index 417fbbd..dd59774 100644 --- a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs +++ b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs @@ -25,7 +25,7 @@ public bool IsExtended } private VirtualizationViewModelState _state; - public VirtualizationViewModelState State + public VirtualizationViewModelState State // TODO add implementation details { get { return _state; } private set { SetValue(ref _state, value); } @@ -79,7 +79,7 @@ public void Expand() public bool CanExpand() { - return false; // TODO add implementation + return ViewModel == null && !IsExtended; } public void Deflate() @@ -90,7 +90,7 @@ public void Deflate() public bool CanDeflate() { - return false; // TODO add implementation + return ViewModel != null && IsExtended; } } } diff --git a/src/Maple.Core/Services/Caching/SimpleInMemoryCacheService.cs b/src/Maple.Core/Services/Caching/SimpleStaticCacheService.cs similarity index 68% rename from src/Maple.Core/Services/Caching/SimpleInMemoryCacheService.cs rename to src/Maple.Core/Services/Caching/SimpleStaticCacheService.cs index 455a61b..e37bff4 100644 --- a/src/Maple.Core/Services/Caching/SimpleInMemoryCacheService.cs +++ b/src/Maple.Core/Services/Caching/SimpleStaticCacheService.cs @@ -2,7 +2,7 @@ namespace Maple.Core { - public class SimpleInMemoryCacheService : Dictionary, ICachingService + public sealed class SimpleStaticCacheService : Dictionary, ICachingService { public bool Contains(TPrimaryKeyType key) { diff --git a/src/Maple.Core/Services/Caching/WeakReferenceCache.cs b/src/Maple.Core/Services/Caching/WeakReferenceCache.cs index 134f988..32bec14 100644 --- a/src/Maple.Core/Services/Caching/WeakReferenceCache.cs +++ b/src/Maple.Core/Services/Caching/WeakReferenceCache.cs @@ -3,7 +3,7 @@ namespace Maple.Core { - public class WeakReferenceCache : ICachingService + public sealed class WeakReferenceCache : ICachingService where TViewModel : class { private readonly ConcurrentDictionary> _references; @@ -15,7 +15,15 @@ public WeakReferenceCache() public bool Add(TPrimaryKeyType key, TViewModel viewModel) { - throw new NotImplementedException(); + throw new NotImplementedException(); // can't accept IDisposeable, since we dont know when the object will be disposed and we cant call Dispose on it + + // Consider + // And finally a word of warning: weak references aren't a guaranteed profit for application performance. + // In most cases, they will make an algorithm more performant than when using very large local variables. + // But it's not guaranteed, and in some cases it could produce noticeable overhead(for example when the huge object is a data structure consisting of many smaller objects with references to each other, + // and a WeakRefence to the data structure turns all those internal refernces to weak references, this might incur garbage collector overhead, + // because every reference has to be checked to decide if the object as a whole can be recovered or deleted). + // So the best advice with weak references is: profile or benchmark it, to make sure that you choose the best solution for your specific situation. } public void Clear() From 54c50e60088a634accc70a7912c0ced3266a4de5 Mon Sep 17 00:00:00 2001 From: Insire Date: Tue, 9 Jan 2018 19:42:04 +0100 Subject: [PATCH 07/16] added first implementation ICachingServices --- .../Services/Caching/ICachingService.cs | 10 +++-- .../Services/Caching/MemoryCacheService.cs | 38 +++++++++++----- .../Services/Caching/WeakReferenceCache.cs | 43 ++++++++++++++----- 3 files changed, 65 insertions(+), 26 deletions(-) diff --git a/src/Maple.Core/Services/Caching/ICachingService.cs b/src/Maple.Core/Services/Caching/ICachingService.cs index 2e51597..d59df0b 100644 --- a/src/Maple.Core/Services/Caching/ICachingService.cs +++ b/src/Maple.Core/Services/Caching/ICachingService.cs @@ -1,11 +1,13 @@ namespace Maple.Core { - public interface ICachingService + public interface ICachingService { - bool Contains(TPrimaryKeyType key); - bool Add(TPrimaryKeyType key, TViewModel viewModel); + bool Contains(TKey key); + bool Add(TKey key, TObject item); + + bool TryGetValue(TKey key, out TObject item); void Clear(); - bool Remove(TPrimaryKeyType key); + bool Remove(TKey key); } } diff --git a/src/Maple.Core/Services/Caching/MemoryCacheService.cs b/src/Maple.Core/Services/Caching/MemoryCacheService.cs index a491f2c..fe10882 100644 --- a/src/Maple.Core/Services/Caching/MemoryCacheService.cs +++ b/src/Maple.Core/Services/Caching/MemoryCacheService.cs @@ -1,14 +1,15 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Runtime.Caching; using Maple.Localization.Properties; namespace Maple.Core { - public abstract class MemoryCacheService : ICachingService - where TViewModel : class + public abstract class MemoryCacheService : ICachingService + where TObject : class { - private readonly HashSet _trackedEntries; + private readonly HashSet _trackedEntries; private readonly MemoryCache _cache; private readonly CacheItemPolicy _policy; private readonly IVirtualizedViewModel _virtualizationProvider; @@ -16,8 +17,8 @@ public abstract class MemoryCacheService : ICaching private MemoryCacheService() { - _cacheKeyPart = typeof(TViewModel).FullName; - _trackedEntries = new HashSet(); + _cacheKeyPart = typeof(TObject).FullName; + _trackedEntries = new HashSet(); _policy = new CacheItemPolicy() { SlidingExpiration = TimeSpan.FromSeconds(3), @@ -33,12 +34,12 @@ protected MemoryCacheService(MemoryCache cache, IVirtualizedViewModel virtualiza _cache = cache ?? throw new ArgumentNullException(nameof(cache), $"{nameof(cache)} {Resources.IsRequired}"); } - public bool Add(TPrimaryKeyType key, TViewModel viewModel) + public bool Add(TKey key, TObject viewModel) { if (viewModel == null) throw new ArgumentNullException(nameof(viewModel), $"{nameof(viewModel)} {Resources.IsRequired}"); - var result = _cache.Add(new CacheItem(_cacheKeyPart + key, viewModel), _policy); + var result = _cache.Add(new CacheItem(GetInternalKey(key), viewModel), _policy); if (result) _trackedEntries.Add(key); @@ -46,7 +47,7 @@ public bool Add(TPrimaryKeyType key, TViewModel viewModel) return result; } - public bool Contains(TPrimaryKeyType key) + public bool Contains(TKey key) { return _cache.Contains(GetInternalKey(key)); } @@ -59,9 +60,9 @@ public void Clear() _trackedEntries.Clear(); } - public bool Remove(TPrimaryKeyType key) + public bool Remove(TKey key) { - var result = _cache.Remove(GetInternalKey(key)) is TViewModel; + var result = _cache.Remove(GetInternalKey(key)) is TObject; if (result) _trackedEntries.Remove(key); @@ -75,9 +76,24 @@ public bool Remove(TPrimaryKeyType key) //} - private string GetInternalKey(TPrimaryKeyType key) + private string GetInternalKey(TKey key) { return _cacheKeyPart + key; } + + public bool TryGetValue(TKey key, out TObject item) + { + item = (TObject)_cache.Get(GetInternalKey(key)); + + return true; + } + + // hm, speed? + public bool TryGetValues(out IEnumerable items, params TKey[] keys) + { + items = _cache.GetValues(keys.Select(key => GetInternalKey(key))).Select(p => p.Value).Cast(); + + return true; + } } } diff --git a/src/Maple.Core/Services/Caching/WeakReferenceCache.cs b/src/Maple.Core/Services/Caching/WeakReferenceCache.cs index 32bec14..f269b3a 100644 --- a/src/Maple.Core/Services/Caching/WeakReferenceCache.cs +++ b/src/Maple.Core/Services/Caching/WeakReferenceCache.cs @@ -3,20 +3,31 @@ namespace Maple.Core { - public sealed class WeakReferenceCache : ICachingService - where TViewModel : class + public sealed class WeakReferenceCache : ICachingService + where TObject : class { - private readonly ConcurrentDictionary> _references; + private readonly ConcurrentDictionary> _references; public WeakReferenceCache() { - _references = new ConcurrentDictionary>(); + _references = new ConcurrentDictionary>(); } - public bool Add(TPrimaryKeyType key, TViewModel viewModel) + public bool Add(TKey key, TObject item) { - throw new NotImplementedException(); // can't accept IDisposeable, since we dont know when the object will be disposed and we cant call Dispose on it + return Add(key, item, false); + } + + public bool Add(TKey key, TObject item, bool isStrongReference) + { + // can't accept IDisposeable, since we dont know when the object will be disposed and we cant call Dispose on it + if (item is IDisposable) + throw new ArgumentException(); + + _references.AddOrUpdate(key, new WeakReference(item), (existingKey, existingEntry) => existingEntry = new WeakReference(item)); + + return true; // Consider // And finally a word of warning: weak references aren't a guaranteed profit for application performance. // In most cases, they will make an algorithm more performant than when using very large local variables. @@ -26,19 +37,29 @@ public bool Add(TPrimaryKeyType key, TViewModel viewModel) // So the best advice with weak references is: profile or benchmark it, to make sure that you choose the best solution for your specific situation. } + public bool TryGetValue(TKey key, out TObject item) + { + item = default(TObject); + + if (_references.TryGetValue(key, out var reference)) + return reference.TryGetTarget(out item); + + return false; + } + public void Clear() { - throw new NotImplementedException(); + _references.Clear(); } - public bool Contains(TPrimaryKeyType key) + public bool Contains(TKey key) { - throw new NotImplementedException(); + return _references.ContainsKey(key); } - public bool Remove(TPrimaryKeyType key) + public bool Remove(TKey key) { - throw new NotImplementedException(); + return _references.TryRemove(key, out _); } } } From c7adb8849210de40a6ea8a242fc0e28858b0b172 Mon Sep 17 00:00:00 2001 From: Insire Date: Tue, 9 Jan 2018 20:15:12 +0100 Subject: [PATCH 08/16] major refactoring: moved platform independent code to maple.core, also updated nuget packages --- src/Maple.Core/Maple.Core.csproj | 67 +++++++++- .../Services}/IMediaRepository.cs | 2 +- .../Services/Mapping}/Base/BaseMapper.cs | 3 +- .../Services/Mapping/Base}/IBaseMapper.cs | 5 +- .../Mapping/Base}/IMediaItemMapper.cs | 2 +- .../Mapping/Base}/IMediaPlayerMapper.cs | 2 +- .../Services/Mapping/Base}/IPlaylistMapper.cs | 2 +- .../Mapping}/Base/MapperExtensions.cs | 3 +- .../Services/Mapping}/MediaItemMapper.cs | 3 +- .../Services/Mapping}/MediaPlayerMapper.cs | 3 +- .../Services/Mapping}/PlaylistMapper.cs | 3 +- .../Services/MediaRepository.cs | 3 +- .../Services/SquirrelLogger.cs | 0 .../Services/Validation/Base/BaseValidator.cs | 2 +- .../Services/Validation/MediaItemValidator.cs | 2 +- .../Validation/MediaPlayerValidator.cs | 2 +- .../Services/Validation/PlaylistValidator.cs | 2 +- .../Services/Validation/PlaylistsValidator.cs | 2 +- .../Services/VersionService.cs | 0 .../Dialogs/Base/DialogBaseViewModel.cs | 3 +- .../Dialogs/Base/IDialogViewModel.cs | 3 +- .../ExceptionContentDialogViewModel.cs | 3 +- .../IO/FileBrowserContentDialogViewModel.cs | 3 +- .../IO/FileSystemBrowserOptions.cs | 4 +- .../IO/FileSystemFolderBrowserOptions.cs | 2 +- .../IO/FolderBrowserContentDialogViewModel.cs | 3 +- .../MessageContentDialogViewModel.cs | 4 +- .../ProgressContentDialogViewModel.cs | 4 +- .../ViewModels/Dialogs/DialogViewModel.cs | 3 +- .../Interfaces/ICultureViewModel.cs | 4 +- .../Interfaces/IMediaItemsViewModel.cs | 3 +- .../Interfaces/IMediaPlayersViewModel.cs | 3 +- .../Interfaces/IPlaylistsViewModel.cs | 4 +- .../Interfaces/ISplashScreenViewModel.cs | 2 +- .../Interfaces/IUIColorsViewModel.cs | 3 +- .../ViewModels/MediaItems/CreateMediaItem.cs | 3 +- .../ViewModels/MediaItems/MediaItem.cs | 3 +- .../ViewModels/MediaItems/MediaItems.cs | 3 +- .../ViewModels/MediaPlayer/AudioDevice.cs | 5 +- .../ViewModels/MediaPlayer/AudioDevices.cs | 3 +- .../ViewModels/MediaPlayer/Base/BasePlayer.cs | 5 +- .../Base}/IPlaybackDeviceFactory.cs | 2 +- .../ViewModels/MediaPlayer/MainMediaPlayer.cs | 3 +- .../ViewModels/MediaPlayer/MediaPlayer.cs | 2 +- .../ViewModels/MediaPlayer/MediaPlayers.cs | 3 +- .../ViewModels/Playlists/CreatePlaylist.cs | 3 +- .../ViewModels/Playlists/Playlist.cs | 2 +- .../ViewModels/Playlists/Playlists.cs | 3 +- .../ViewModels/Settings/Culture.cs | 3 +- .../ViewModels/Settings/Cultures.cs | 3 +- .../ViewModels/Settings/OptionsViewModel.cs | 3 +- .../ViewModels/SplashScreenViewModel.cs | 3 +- .../ViewModels/StatusbarViewModel.cs | 3 +- src/Maple.Data/Maple.Data.csproj | 2 +- src/Maple.Test/Maple.Test.csproj | 2 +- .../ViewModels/Playlists/PlaylistsTests.cs | 1 + src/Maple.Youtube/Maple.Youtube.csproj | 6 +- src/Maple/Maple.csproj | 115 ++++-------------- src/Maple/Resources/Style.xaml | 20 +-- .../Base}/IConfigurableWindowSettings.cs | 0 .../Base}/IIocFrameworkElement.cs | 0 src/Maple/UI/PackIcon.cs | 2 +- .../NAudio/PlaybackDeviceFactory.cs | 1 + src/Maple/ViewModels/Navigation/Scene.cs | 5 - .../{Settings => }/UIColorsViewModel.cs | 0 65 files changed, 159 insertions(+), 209 deletions(-) rename src/{Maple/Interfaces => Maple.Core/Services}/IMediaRepository.cs (97%) rename src/{Maple/Services/Mappers => Maple.Core/Services/Mapping}/Base/BaseMapper.cs (97%) rename src/{Maple/Interfaces => Maple.Core/Services/Mapping/Base}/IBaseMapper.cs (84%) rename src/{Maple/Interfaces => Maple.Core/Services/Mapping/Base}/IMediaItemMapper.cs (92%) rename src/{Maple/Interfaces => Maple.Core/Services/Mapping/Base}/IMediaPlayerMapper.cs (94%) rename src/{Maple/Interfaces => Maple.Core/Services/Mapping/Base}/IPlaylistMapper.cs (88%) rename src/{Maple/Services/Mappers => Maple.Core/Services/Mapping}/Base/MapperExtensions.cs (97%) rename src/{Maple/Services/Mappers => Maple.Core/Services/Mapping}/MediaItemMapper.cs (98%) rename src/{Maple/Services/Mappers => Maple.Core/Services/Mapping}/MediaPlayerMapper.cs (98%) rename src/{Maple/Services/Mappers => Maple.Core/Services/Mapping}/PlaylistMapper.cs (98%) rename src/{Maple => Maple.Core}/Services/MediaRepository.cs (99%) rename src/{Maple => Maple.Core}/Services/SquirrelLogger.cs (100%) rename src/{Maple => Maple.Core}/Services/Validation/Base/BaseValidator.cs (96%) rename src/{Maple => Maple.Core}/Services/Validation/MediaItemValidator.cs (95%) rename src/{Maple => Maple.Core}/Services/Validation/MediaPlayerValidator.cs (96%) rename src/{Maple => Maple.Core}/Services/Validation/PlaylistValidator.cs (97%) rename src/{Maple => Maple.Core}/Services/Validation/PlaylistsValidator.cs (95%) rename src/{Maple => Maple.Core}/Services/VersionService.cs (100%) rename src/{Maple => Maple.Core}/ViewModels/Dialogs/Base/DialogBaseViewModel.cs (99%) rename src/{Maple => Maple.Core}/ViewModels/Dialogs/Base/IDialogViewModel.cs (96%) rename src/{Maple => Maple.Core}/ViewModels/Dialogs/DialogContentViewModels/ExceptionContentDialogViewModel.cs (92%) rename src/{Maple => Maple.Core}/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs (96%) rename src/{Maple => Maple.Core}/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemBrowserOptions.cs (94%) rename src/{Maple => Maple.Core}/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemFolderBrowserOptions.cs (92%) rename src/{Maple => Maple.Core}/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs (96%) rename src/{Maple => Maple.Core}/ViewModels/Dialogs/DialogContentViewModels/MessageContentDialogViewModel.cs (86%) rename src/{Maple => Maple.Core}/ViewModels/Dialogs/DialogContentViewModels/ProgressContentDialogViewModel.cs (68%) rename src/{Maple => Maple.Core}/ViewModels/Dialogs/DialogViewModel.cs (99%) rename src/{Maple => Maple.Core}/ViewModels/Interfaces/ICultureViewModel.cs (71%) rename src/{Maple => Maple.Core}/ViewModels/Interfaces/IMediaItemsViewModel.cs (87%) rename src/{Maple => Maple.Core}/ViewModels/Interfaces/IMediaPlayersViewModel.cs (86%) rename src/{Maple => Maple.Core}/ViewModels/Interfaces/IPlaylistsViewModel.cs (75%) rename src/{Maple => Maple.Core}/ViewModels/Interfaces/ISplashScreenViewModel.cs (92%) rename src/{Maple => Maple.Core}/ViewModels/Interfaces/IUIColorsViewModel.cs (90%) rename src/{Maple => Maple.Core}/ViewModels/MediaItems/CreateMediaItem.cs (98%) rename src/{Maple => Maple.Core}/ViewModels/MediaItems/MediaItem.cs (99%) rename src/{Maple => Maple.Core}/ViewModels/MediaItems/MediaItems.cs (98%) rename src/{Maple => Maple.Core}/ViewModels/MediaPlayer/AudioDevice.cs (95%) rename src/{Maple => Maple.Core}/ViewModels/MediaPlayer/AudioDevices.cs (90%) rename src/{Maple => Maple.Core}/ViewModels/MediaPlayer/Base/BasePlayer.cs (96%) rename src/{Maple/ViewModels/MediaPlayer/NAudio => Maple.Core/ViewModels/MediaPlayer/Base}/IPlaybackDeviceFactory.cs (90%) rename src/{Maple => Maple.Core}/ViewModels/MediaPlayer/MainMediaPlayer.cs (96%) rename src/{Maple => Maple.Core}/ViewModels/MediaPlayer/MediaPlayer.cs (99%) rename src/{Maple => Maple.Core}/ViewModels/MediaPlayer/MediaPlayers.cs (99%) rename src/{Maple => Maple.Core}/ViewModels/Playlists/CreatePlaylist.cs (98%) rename src/{Maple => Maple.Core}/ViewModels/Playlists/Playlist.cs (99%) rename src/{Maple => Maple.Core}/ViewModels/Playlists/Playlists.cs (98%) rename src/{Maple => Maple.Core}/ViewModels/Settings/Culture.cs (89%) rename src/{Maple => Maple.Core}/ViewModels/Settings/Cultures.cs (98%) rename src/{Maple => Maple.Core}/ViewModels/Settings/OptionsViewModel.cs (96%) rename src/{Maple => Maple.Core}/ViewModels/SplashScreenViewModel.cs (99%) rename src/{Maple => Maple.Core}/ViewModels/StatusbarViewModel.cs (98%) rename src/Maple/{Interfaces => UI/Base}/IConfigurableWindowSettings.cs (100%) rename src/Maple/{Interfaces => UI/Base}/IIocFrameworkElement.cs (100%) rename src/Maple/ViewModels/{Settings => }/UIColorsViewModel.cs (100%) diff --git a/src/Maple.Core/Maple.Core.csproj b/src/Maple.Core/Maple.Core.csproj index 4023e76..adf149c 100644 --- a/src/Maple.Core/Maple.Core.csproj +++ b/src/Maple.Core/Maple.Core.csproj @@ -33,9 +33,12 @@ 4 + + 6.2.2 + - + 2.2.0 @@ -44,7 +47,10 @@ - + + + 1.7.8 + @@ -163,6 +169,15 @@ + + + + + + + + + @@ -174,9 +189,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -200,7 +258,10 @@ {A073FC92-90E3-4541-8B52-6F7293187871} Maple.Localization + + {b5be546f-8d9f-4fb9-b235-af05fd553f9e} + Maple.Youtube + - \ No newline at end of file diff --git a/src/Maple/Interfaces/IMediaRepository.cs b/src/Maple.Core/Services/IMediaRepository.cs similarity index 97% rename from src/Maple/Interfaces/IMediaRepository.cs rename to src/Maple.Core/Services/IMediaRepository.cs index 7b7f1eb..a2769d8 100644 --- a/src/Maple/Interfaces/IMediaRepository.cs +++ b/src/Maple.Core/Services/IMediaRepository.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Maple +namespace Maple.Core { public interface IMediaRepository : IDisposable { diff --git a/src/Maple/Services/Mappers/Base/BaseMapper.cs b/src/Maple.Core/Services/Mapping/Base/BaseMapper.cs similarity index 97% rename from src/Maple/Services/Mappers/Base/BaseMapper.cs rename to src/Maple.Core/Services/Mapping/Base/BaseMapper.cs index 74fa2f9..09a81cd 100644 --- a/src/Maple/Services/Mappers/Base/BaseMapper.cs +++ b/src/Maple.Core/Services/Mapping/Base/BaseMapper.cs @@ -1,11 +1,10 @@ using System; using AutoMapper; using FluentValidation; -using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { public abstract class BaseMapper { diff --git a/src/Maple/Interfaces/IBaseMapper.cs b/src/Maple.Core/Services/Mapping/Base/IBaseMapper.cs similarity index 84% rename from src/Maple/Interfaces/IBaseMapper.cs rename to src/Maple.Core/Services/Mapping/Base/IBaseMapper.cs index 8ef2edb..8352d95 100644 --- a/src/Maple/Interfaces/IBaseMapper.cs +++ b/src/Maple.Core/Services/Mapping/Base/IBaseMapper.cs @@ -1,7 +1,6 @@ -using Maple.Core; -using Maple.Domain; +using Maple.Domain; -namespace Maple +namespace Maple.Core { public interface IBaseMapper where TVieModel : BaseDataViewModel diff --git a/src/Maple/Interfaces/IMediaItemMapper.cs b/src/Maple.Core/Services/Mapping/Base/IMediaItemMapper.cs similarity index 92% rename from src/Maple/Interfaces/IMediaItemMapper.cs rename to src/Maple.Core/Services/Mapping/Base/IMediaItemMapper.cs index b8e453f..ea4c5ae 100644 --- a/src/Maple/Interfaces/IMediaItemMapper.cs +++ b/src/Maple.Core/Services/Mapping/Base/IMediaItemMapper.cs @@ -1,6 +1,6 @@ using Maple.Domain; -namespace Maple +namespace Maple.Core { public interface IMediaItemMapper : IBaseMapper { diff --git a/src/Maple/Interfaces/IMediaPlayerMapper.cs b/src/Maple.Core/Services/Mapping/Base/IMediaPlayerMapper.cs similarity index 94% rename from src/Maple/Interfaces/IMediaPlayerMapper.cs rename to src/Maple.Core/Services/Mapping/Base/IMediaPlayerMapper.cs index 7097556..bcf9bc3 100644 --- a/src/Maple/Interfaces/IMediaPlayerMapper.cs +++ b/src/Maple.Core/Services/Mapping/Base/IMediaPlayerMapper.cs @@ -1,6 +1,6 @@ using Maple.Domain; -namespace Maple +namespace Maple.Core { public interface IMediaPlayerMapper : IBaseMapper { diff --git a/src/Maple/Interfaces/IPlaylistMapper.cs b/src/Maple.Core/Services/Mapping/Base/IPlaylistMapper.cs similarity index 88% rename from src/Maple/Interfaces/IPlaylistMapper.cs rename to src/Maple.Core/Services/Mapping/Base/IPlaylistMapper.cs index bdcf15e..daa37ca 100644 --- a/src/Maple/Interfaces/IPlaylistMapper.cs +++ b/src/Maple.Core/Services/Mapping/Base/IPlaylistMapper.cs @@ -1,6 +1,6 @@ using Maple.Domain; -namespace Maple +namespace Maple.Core { public interface IPlaylistMapper : IBaseMapper { diff --git a/src/Maple/Services/Mappers/Base/MapperExtensions.cs b/src/Maple.Core/Services/Mapping/Base/MapperExtensions.cs similarity index 97% rename from src/Maple/Services/Mappers/Base/MapperExtensions.cs rename to src/Maple.Core/Services/Mapping/Base/MapperExtensions.cs index 5836b58..de65f6d 100644 --- a/src/Maple/Services/Mappers/Base/MapperExtensions.cs +++ b/src/Maple.Core/Services/Mapping/Base/MapperExtensions.cs @@ -3,9 +3,8 @@ using System.Linq; using System.Linq.Expressions; using AutoMapper; -using Maple.Core; -namespace Maple +namespace Maple.Core { /// /// Extensions for diff --git a/src/Maple/Services/Mappers/MediaItemMapper.cs b/src/Maple.Core/Services/Mapping/MediaItemMapper.cs similarity index 98% rename from src/Maple/Services/Mappers/MediaItemMapper.cs rename to src/Maple.Core/Services/Mapping/MediaItemMapper.cs index d6fbc16..4ffc84c 100644 --- a/src/Maple/Services/Mappers/MediaItemMapper.cs +++ b/src/Maple.Core/Services/Mapping/MediaItemMapper.cs @@ -1,10 +1,9 @@ using AutoMapper; using FluentValidation; -using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { /// /// Provides logic to map between different domain objects of the MediaItemType diff --git a/src/Maple/Services/Mappers/MediaPlayerMapper.cs b/src/Maple.Core/Services/Mapping/MediaPlayerMapper.cs similarity index 98% rename from src/Maple/Services/Mappers/MediaPlayerMapper.cs rename to src/Maple.Core/Services/Mapping/MediaPlayerMapper.cs index fdc7207..76a3dd3 100644 --- a/src/Maple/Services/Mappers/MediaPlayerMapper.cs +++ b/src/Maple.Core/Services/Mapping/MediaPlayerMapper.cs @@ -1,11 +1,10 @@ using System; using AutoMapper; using FluentValidation; -using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { public sealed class MediaPlayerMapper : BaseMapper, IMediaPlayerMapper { diff --git a/src/Maple/Services/Mappers/PlaylistMapper.cs b/src/Maple.Core/Services/Mapping/PlaylistMapper.cs similarity index 98% rename from src/Maple/Services/Mappers/PlaylistMapper.cs rename to src/Maple.Core/Services/Mapping/PlaylistMapper.cs index c8d2d5d..190024f 100644 --- a/src/Maple/Services/Mappers/PlaylistMapper.cs +++ b/src/Maple.Core/Services/Mapping/PlaylistMapper.cs @@ -1,11 +1,10 @@ using System; using AutoMapper; using FluentValidation; -using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { /// /// Provides logic to map between different domain objects of the Playlisttype diff --git a/src/Maple/Services/MediaRepository.cs b/src/Maple.Core/Services/MediaRepository.cs similarity index 99% rename from src/Maple/Services/MediaRepository.cs rename to src/Maple.Core/Services/MediaRepository.cs index 99c2580..8bba135 100644 --- a/src/Maple/Services/MediaRepository.cs +++ b/src/Maple.Core/Services/MediaRepository.cs @@ -3,11 +3,10 @@ using System.Diagnostics; using System.Linq; using System.Threading.Tasks; -using Maple.Core; using Maple.Data; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { // helpful: https://blog.oneunicorn.com/2012/03/10/secrets-of-detectchanges-part-1-what-does-detectchanges-do/ /// diff --git a/src/Maple/Services/SquirrelLogger.cs b/src/Maple.Core/Services/SquirrelLogger.cs similarity index 100% rename from src/Maple/Services/SquirrelLogger.cs rename to src/Maple.Core/Services/SquirrelLogger.cs diff --git a/src/Maple/Services/Validation/Base/BaseValidator.cs b/src/Maple.Core/Services/Validation/Base/BaseValidator.cs similarity index 96% rename from src/Maple/Services/Validation/Base/BaseValidator.cs rename to src/Maple.Core/Services/Validation/Base/BaseValidator.cs index 9da734b..2329137 100644 --- a/src/Maple/Services/Validation/Base/BaseValidator.cs +++ b/src/Maple.Core/Services/Validation/Base/BaseValidator.cs @@ -2,7 +2,7 @@ using FluentValidation; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { public abstract class BaseValidator : AbstractValidator, IValidator { diff --git a/src/Maple/Services/Validation/MediaItemValidator.cs b/src/Maple.Core/Services/Validation/MediaItemValidator.cs similarity index 95% rename from src/Maple/Services/Validation/MediaItemValidator.cs rename to src/Maple.Core/Services/Validation/MediaItemValidator.cs index 23cd0c7..e726471 100644 --- a/src/Maple/Services/Validation/MediaItemValidator.cs +++ b/src/Maple.Core/Services/Validation/MediaItemValidator.cs @@ -1,6 +1,6 @@ using FluentValidation; -namespace Maple +namespace Maple.Core { public class MediaItemValidator : BaseValidator, IValidator { diff --git a/src/Maple/Services/Validation/MediaPlayerValidator.cs b/src/Maple.Core/Services/Validation/MediaPlayerValidator.cs similarity index 96% rename from src/Maple/Services/Validation/MediaPlayerValidator.cs rename to src/Maple.Core/Services/Validation/MediaPlayerValidator.cs index 37d0e07..1763dd0 100644 --- a/src/Maple/Services/Validation/MediaPlayerValidator.cs +++ b/src/Maple.Core/Services/Validation/MediaPlayerValidator.cs @@ -1,6 +1,6 @@ using FluentValidation; -namespace Maple +namespace Maple.Core { public class MediaPlayerValidator : BaseValidator, IValidator { diff --git a/src/Maple/Services/Validation/PlaylistValidator.cs b/src/Maple.Core/Services/Validation/PlaylistValidator.cs similarity index 97% rename from src/Maple/Services/Validation/PlaylistValidator.cs rename to src/Maple.Core/Services/Validation/PlaylistValidator.cs index 667d0de..2aee28f 100644 --- a/src/Maple/Services/Validation/PlaylistValidator.cs +++ b/src/Maple.Core/Services/Validation/PlaylistValidator.cs @@ -1,6 +1,6 @@ using FluentValidation; -namespace Maple +namespace Maple.Core { public class PlaylistValidator : BaseValidator, IValidator { diff --git a/src/Maple/Services/Validation/PlaylistsValidator.cs b/src/Maple.Core/Services/Validation/PlaylistsValidator.cs similarity index 95% rename from src/Maple/Services/Validation/PlaylistsValidator.cs rename to src/Maple.Core/Services/Validation/PlaylistsValidator.cs index 8edd389..403a159 100644 --- a/src/Maple/Services/Validation/PlaylistsValidator.cs +++ b/src/Maple.Core/Services/Validation/PlaylistsValidator.cs @@ -1,6 +1,6 @@ using FluentValidation; -namespace Maple +namespace Maple.Core { public class PlaylistsValidator : BaseValidator, IValidator { diff --git a/src/Maple/Services/VersionService.cs b/src/Maple.Core/Services/VersionService.cs similarity index 100% rename from src/Maple/Services/VersionService.cs rename to src/Maple.Core/Services/VersionService.cs diff --git a/src/Maple/ViewModels/Dialogs/Base/DialogBaseViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/Base/DialogBaseViewModel.cs similarity index 99% rename from src/Maple/ViewModels/Dialogs/Base/DialogBaseViewModel.cs rename to src/Maple.Core/ViewModels/Dialogs/Base/DialogBaseViewModel.cs index e05fbd6..f306371 100644 --- a/src/Maple/ViewModels/Dialogs/Base/DialogBaseViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/Base/DialogBaseViewModel.cs @@ -2,9 +2,8 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Input; -using Maple.Core; -namespace Maple +namespace Maple.Core { public abstract class DialogBaseViewModel : ViewModel { diff --git a/src/Maple/ViewModels/Dialogs/Base/IDialogViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/Base/IDialogViewModel.cs similarity index 96% rename from src/Maple/ViewModels/Dialogs/Base/IDialogViewModel.cs rename to src/Maple.Core/ViewModels/Dialogs/Base/IDialogViewModel.cs index e517e82..b440013 100644 --- a/src/Maple/ViewModels/Dialogs/Base/IDialogViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/Base/IDialogViewModel.cs @@ -2,9 +2,8 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Maple.Core; -namespace Maple +namespace Maple.Core { public interface IDialogViewModel { diff --git a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/ExceptionContentDialogViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/ExceptionContentDialogViewModel.cs similarity index 92% rename from src/Maple/ViewModels/Dialogs/DialogContentViewModels/ExceptionContentDialogViewModel.cs rename to src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/ExceptionContentDialogViewModel.cs index 9fbae6a..c157b60 100644 --- a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/ExceptionContentDialogViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/ExceptionContentDialogViewModel.cs @@ -1,7 +1,6 @@ using System; -using Maple.Core; -namespace Maple +namespace Maple.Core { public class ExceptionContentDialogViewModel : ObservableObject { diff --git a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs similarity index 96% rename from src/Maple/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs rename to src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs index 3c9377b..47863f5 100644 --- a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs @@ -1,8 +1,7 @@ using System; -using Maple.Core; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { public class FileBrowserContentDialogViewModel : ObservableObject { diff --git a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemBrowserOptions.cs b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemBrowserOptions.cs similarity index 94% rename from src/Maple/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemBrowserOptions.cs rename to src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemBrowserOptions.cs index 02f388e..15d41c5 100644 --- a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemBrowserOptions.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemBrowserOptions.cs @@ -1,6 +1,4 @@ -using Maple.Core; - -namespace Maple +namespace Maple.Core { public class FileSystemBrowserOptions : ObservableObject { diff --git a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemFolderBrowserOptions.cs b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemFolderBrowserOptions.cs similarity index 92% rename from src/Maple/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemFolderBrowserOptions.cs rename to src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemFolderBrowserOptions.cs index ce464be..a43e3ea 100644 --- a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemFolderBrowserOptions.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileSystemFolderBrowserOptions.cs @@ -1,4 +1,4 @@ -namespace Maple +namespace Maple.Core { public class FileSystemFolderBrowserOptions : FileSystemBrowserOptions { diff --git a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs similarity index 96% rename from src/Maple/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs rename to src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs index cba7ecc..fd3031a 100644 --- a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs @@ -1,8 +1,7 @@ using System; -using Maple.Core; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { public class FolderBrowserContentDialogViewModel : ObservableObject { diff --git a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/MessageContentDialogViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/MessageContentDialogViewModel.cs similarity index 86% rename from src/Maple/ViewModels/Dialogs/DialogContentViewModels/MessageContentDialogViewModel.cs rename to src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/MessageContentDialogViewModel.cs index 02a4621..f1260db 100644 --- a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/MessageContentDialogViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/MessageContentDialogViewModel.cs @@ -1,6 +1,4 @@ -using Maple.Core; - -namespace Maple +namespace Maple.Core { public class MessageContentDialogViewModel : ObservableObject { diff --git a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/ProgressContentDialogViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/ProgressContentDialogViewModel.cs similarity index 68% rename from src/Maple/ViewModels/Dialogs/DialogContentViewModels/ProgressContentDialogViewModel.cs rename to src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/ProgressContentDialogViewModel.cs index 3381bff..4cfdbbd 100644 --- a/src/Maple/ViewModels/Dialogs/DialogContentViewModels/ProgressContentDialogViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/ProgressContentDialogViewModel.cs @@ -1,6 +1,4 @@ -using Maple.Core; - -namespace Maple +namespace Maple.Core { public class ProgressContentDialogViewModel : ObservableObject { diff --git a/src/Maple/ViewModels/Dialogs/DialogViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/DialogViewModel.cs similarity index 99% rename from src/Maple/ViewModels/Dialogs/DialogViewModel.cs rename to src/Maple.Core/ViewModels/Dialogs/DialogViewModel.cs index 7da5526..a3a368c 100644 --- a/src/Maple/ViewModels/Dialogs/DialogViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogViewModel.cs @@ -3,11 +3,10 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Maple.Core; using Maple.Localization.Properties; using Maple.Youtube; -namespace Maple +namespace Maple.Core { public class DialogViewModel : DialogBaseViewModel, IDialogViewModel { diff --git a/src/Maple/ViewModels/Interfaces/ICultureViewModel.cs b/src/Maple.Core/ViewModels/Interfaces/ICultureViewModel.cs similarity index 71% rename from src/Maple/ViewModels/Interfaces/ICultureViewModel.cs rename to src/Maple.Core/ViewModels/Interfaces/ICultureViewModel.cs index 1af604a..1322922 100644 --- a/src/Maple/ViewModels/Interfaces/ICultureViewModel.cs +++ b/src/Maple.Core/ViewModels/Interfaces/ICultureViewModel.cs @@ -1,6 +1,4 @@ -using Maple.Core; - -namespace Maple +namespace Maple.Core { public interface ICultureViewModel : ILoadableViewModel, ISaveableViewModel { diff --git a/src/Maple/ViewModels/Interfaces/IMediaItemsViewModel.cs b/src/Maple.Core/ViewModels/Interfaces/IMediaItemsViewModel.cs similarity index 87% rename from src/Maple/ViewModels/Interfaces/IMediaItemsViewModel.cs rename to src/Maple.Core/ViewModels/Interfaces/IMediaItemsViewModel.cs index 5244716..1c1c91b 100644 --- a/src/Maple/ViewModels/Interfaces/IMediaItemsViewModel.cs +++ b/src/Maple.Core/ViewModels/Interfaces/IMediaItemsViewModel.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; -using Maple.Core; -namespace Maple +namespace Maple.Core { public interface IMediaItemsViewModel : ILoadableViewModel, ISaveableViewModel { diff --git a/src/Maple/ViewModels/Interfaces/IMediaPlayersViewModel.cs b/src/Maple.Core/ViewModels/Interfaces/IMediaPlayersViewModel.cs similarity index 86% rename from src/Maple/ViewModels/Interfaces/IMediaPlayersViewModel.cs rename to src/Maple.Core/ViewModels/Interfaces/IMediaPlayersViewModel.cs index b035984..201e677 100644 --- a/src/Maple/ViewModels/Interfaces/IMediaPlayersViewModel.cs +++ b/src/Maple.Core/ViewModels/Interfaces/IMediaPlayersViewModel.cs @@ -1,8 +1,7 @@ using System; using System.Collections.Generic; -using Maple.Core; -namespace Maple +namespace Maple.Core { public interface IMediaPlayersViewModel : ILoadableViewModel, ISaveableViewModel, IDisposable { diff --git a/src/Maple/ViewModels/Interfaces/IPlaylistsViewModel.cs b/src/Maple.Core/ViewModels/Interfaces/IPlaylistsViewModel.cs similarity index 75% rename from src/Maple/ViewModels/Interfaces/IPlaylistsViewModel.cs rename to src/Maple.Core/ViewModels/Interfaces/IPlaylistsViewModel.cs index 2c2a01a..e28ac9f 100644 --- a/src/Maple/ViewModels/Interfaces/IPlaylistsViewModel.cs +++ b/src/Maple.Core/ViewModels/Interfaces/IPlaylistsViewModel.cs @@ -1,6 +1,4 @@ -using Maple.Core; - -namespace Maple +namespace Maple.Core { public interface IPlaylistsViewModel : ILoadableViewModel, ISaveableViewModel { diff --git a/src/Maple/ViewModels/Interfaces/ISplashScreenViewModel.cs b/src/Maple.Core/ViewModels/Interfaces/ISplashScreenViewModel.cs similarity index 92% rename from src/Maple/ViewModels/Interfaces/ISplashScreenViewModel.cs rename to src/Maple.Core/ViewModels/Interfaces/ISplashScreenViewModel.cs index c17a849..5c01b0e 100644 --- a/src/Maple/ViewModels/Interfaces/ISplashScreenViewModel.cs +++ b/src/Maple.Core/ViewModels/Interfaces/ISplashScreenViewModel.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Input; -namespace Maple +namespace Maple.Core { public interface ISplashScreenViewModel : IDisposable { diff --git a/src/Maple/ViewModels/Interfaces/IUIColorsViewModel.cs b/src/Maple.Core/ViewModels/Interfaces/IUIColorsViewModel.cs similarity index 90% rename from src/Maple/ViewModels/Interfaces/IUIColorsViewModel.cs rename to src/Maple.Core/ViewModels/Interfaces/IUIColorsViewModel.cs index eca7058..97591bf 100644 --- a/src/Maple/ViewModels/Interfaces/IUIColorsViewModel.cs +++ b/src/Maple.Core/ViewModels/Interfaces/IUIColorsViewModel.cs @@ -1,7 +1,6 @@ using System.Windows.Input; -using Maple.Core; -namespace Maple +namespace Maple.Core { public interface IUIColorsViewModel : ILoadableViewModel, ISaveableViewModel { diff --git a/src/Maple/ViewModels/MediaItems/CreateMediaItem.cs b/src/Maple.Core/ViewModels/MediaItems/CreateMediaItem.cs similarity index 98% rename from src/Maple/ViewModels/MediaItems/CreateMediaItem.cs rename to src/Maple.Core/ViewModels/MediaItems/CreateMediaItem.cs index 07a16b8..4fbf349 100644 --- a/src/Maple/ViewModels/MediaItems/CreateMediaItem.cs +++ b/src/Maple.Core/ViewModels/MediaItems/CreateMediaItem.cs @@ -1,11 +1,10 @@ using System; using System.Threading.Tasks; using System.Windows.Input; -using Maple.Core; using Maple.Localization.Properties; using Maple.Youtube; -namespace Maple +namespace Maple.Core { /// /// viewmodel for creating mediaitem from a string (path/url) diff --git a/src/Maple/ViewModels/MediaItems/MediaItem.cs b/src/Maple.Core/ViewModels/MediaItems/MediaItem.cs similarity index 99% rename from src/Maple/ViewModels/MediaItems/MediaItem.cs rename to src/Maple.Core/ViewModels/MediaItems/MediaItem.cs index b93098b..adbc43d 100644 --- a/src/Maple/ViewModels/MediaItems/MediaItem.cs +++ b/src/Maple.Core/ViewModels/MediaItems/MediaItem.cs @@ -1,10 +1,9 @@ using System; using System.Diagnostics; using FluentValidation; -using Maple.Core; using Maple.Domain; -namespace Maple +namespace Maple.Core { /// /// diff --git a/src/Maple/ViewModels/MediaItems/MediaItems.cs b/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs similarity index 98% rename from src/Maple/ViewModels/MediaItems/MediaItems.cs rename to src/Maple.Core/ViewModels/MediaItems/MediaItems.cs index 3a9b45f..2b29571 100644 --- a/src/Maple/ViewModels/MediaItems/MediaItems.cs +++ b/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs @@ -1,11 +1,10 @@ using System; using System.Linq; using System.Threading.Tasks; -using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { public class MediaItems : VirtualizationListViewModel, IMediaItemsViewModel { diff --git a/src/Maple/ViewModels/MediaPlayer/AudioDevice.cs b/src/Maple.Core/ViewModels/MediaPlayer/AudioDevice.cs similarity index 95% rename from src/Maple/ViewModels/MediaPlayer/AudioDevice.cs rename to src/Maple.Core/ViewModels/MediaPlayer/AudioDevice.cs index b94a5ea..11d930d 100644 --- a/src/Maple/ViewModels/MediaPlayer/AudioDevice.cs +++ b/src/Maple.Core/ViewModels/MediaPlayer/AudioDevice.cs @@ -1,7 +1,6 @@ -using Maple.Core; -using Maple.Domain; +using Maple.Domain; -namespace Maple +namespace Maple.Core { public class AudioDevice : ObservableObject, IIsSelected, ISequence, IAudioDevice { diff --git a/src/Maple/ViewModels/MediaPlayer/AudioDevices.cs b/src/Maple.Core/ViewModels/MediaPlayer/AudioDevices.cs similarity index 90% rename from src/Maple/ViewModels/MediaPlayer/AudioDevices.cs rename to src/Maple.Core/ViewModels/MediaPlayer/AudioDevices.cs index d3d6fe6..503167d 100644 --- a/src/Maple/ViewModels/MediaPlayer/AudioDevices.cs +++ b/src/Maple.Core/ViewModels/MediaPlayer/AudioDevices.cs @@ -1,8 +1,7 @@ using System.Linq; -using Maple.Core; using Maple.Domain; -namespace Maple +namespace Maple.Core { public class AudioDevices : BaseListViewModel { diff --git a/src/Maple/ViewModels/MediaPlayer/Base/BasePlayer.cs b/src/Maple.Core/ViewModels/MediaPlayer/Base/BasePlayer.cs similarity index 96% rename from src/Maple/ViewModels/MediaPlayer/Base/BasePlayer.cs rename to src/Maple.Core/ViewModels/MediaPlayer/Base/BasePlayer.cs index 0a5f181..794f62c 100644 --- a/src/Maple/ViewModels/MediaPlayer/Base/BasePlayer.cs +++ b/src/Maple.Core/ViewModels/MediaPlayer/Base/BasePlayer.cs @@ -1,7 +1,6 @@ -using Maple.Core; -using Maple.Domain; +using Maple.Domain; -namespace Maple +namespace Maple.Core { public abstract class BasePlayer : ViewModel, IMediaPlayer { diff --git a/src/Maple/ViewModels/MediaPlayer/NAudio/IPlaybackDeviceFactory.cs b/src/Maple.Core/ViewModels/MediaPlayer/Base/IPlaybackDeviceFactory.cs similarity index 90% rename from src/Maple/ViewModels/MediaPlayer/NAudio/IPlaybackDeviceFactory.cs rename to src/Maple.Core/ViewModels/MediaPlayer/Base/IPlaybackDeviceFactory.cs index 375e7d8..501d7fa 100644 --- a/src/Maple/ViewModels/MediaPlayer/NAudio/IPlaybackDeviceFactory.cs +++ b/src/Maple.Core/ViewModels/MediaPlayer/Base/IPlaybackDeviceFactory.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using Maple.Domain; -namespace Maple +namespace Maple.Core { public interface IPlaybackDeviceFactory { diff --git a/src/Maple/ViewModels/MediaPlayer/MainMediaPlayer.cs b/src/Maple.Core/ViewModels/MediaPlayer/MainMediaPlayer.cs similarity index 96% rename from src/Maple/ViewModels/MediaPlayer/MainMediaPlayer.cs rename to src/Maple.Core/ViewModels/MediaPlayer/MainMediaPlayer.cs index e5513ed..ddf759c 100644 --- a/src/Maple/ViewModels/MediaPlayer/MainMediaPlayer.cs +++ b/src/Maple.Core/ViewModels/MediaPlayer/MainMediaPlayer.cs @@ -1,9 +1,8 @@ using FluentValidation; -using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { public class MainMediaPlayer : MediaPlayer { diff --git a/src/Maple/ViewModels/MediaPlayer/MediaPlayer.cs b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayer.cs similarity index 99% rename from src/Maple/ViewModels/MediaPlayer/MediaPlayer.cs rename to src/Maple.Core/ViewModels/MediaPlayer/MediaPlayer.cs index 7fc705f..7bf0f42 100644 --- a/src/Maple/ViewModels/MediaPlayer/MediaPlayer.cs +++ b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayer.cs @@ -8,7 +8,7 @@ using Maple.Domain; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { [DebuggerDisplay("{Name}, {Sequence}")] public class MediaPlayer : ValidableBaseDataViewModel, IDisposable, IChangeState, ISequence diff --git a/src/Maple/ViewModels/MediaPlayer/MediaPlayers.cs b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs similarity index 99% rename from src/Maple/ViewModels/MediaPlayer/MediaPlayers.cs rename to src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs index b6d81dc..582a2b3 100644 --- a/src/Maple/ViewModels/MediaPlayer/MediaPlayers.cs +++ b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs @@ -1,11 +1,10 @@ using System; using System.Linq; using System.Threading.Tasks; -using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { public class MediaPlayers : VirtualizationListViewModel, IMediaPlayersViewModel { diff --git a/src/Maple/ViewModels/Playlists/CreatePlaylist.cs b/src/Maple.Core/ViewModels/Playlists/CreatePlaylist.cs similarity index 98% rename from src/Maple/ViewModels/Playlists/CreatePlaylist.cs rename to src/Maple.Core/ViewModels/Playlists/CreatePlaylist.cs index 6fff809..6ac2c40 100644 --- a/src/Maple/ViewModels/Playlists/CreatePlaylist.cs +++ b/src/Maple.Core/ViewModels/Playlists/CreatePlaylist.cs @@ -1,9 +1,8 @@ using System.Threading.Tasks; using System.Windows.Input; -using Maple.Core; using Maple.Youtube; -namespace Maple +namespace Maple.Core { /// /// viewmodel for creating playlists from a input string (path/url) diff --git a/src/Maple/ViewModels/Playlists/Playlist.cs b/src/Maple.Core/ViewModels/Playlists/Playlist.cs similarity index 99% rename from src/Maple/ViewModels/Playlists/Playlist.cs rename to src/Maple.Core/ViewModels/Playlists/Playlist.cs index 0e541c4..03448dd 100644 --- a/src/Maple/ViewModels/Playlists/Playlist.cs +++ b/src/Maple.Core/ViewModels/Playlists/Playlist.cs @@ -13,7 +13,7 @@ using Maple.Domain; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { [DebuggerDisplay("{Title}, {Sequence}")] public class Playlist : ValidableBaseDataViewModel, IIsSelected, ISequence, IIdentifier, IChangeState diff --git a/src/Maple/ViewModels/Playlists/Playlists.cs b/src/Maple.Core/ViewModels/Playlists/Playlists.cs similarity index 98% rename from src/Maple/ViewModels/Playlists/Playlists.cs rename to src/Maple.Core/ViewModels/Playlists/Playlists.cs index 0b62f6e..cdaa8e3 100644 --- a/src/Maple/ViewModels/Playlists/Playlists.cs +++ b/src/Maple.Core/ViewModels/Playlists/Playlists.cs @@ -1,11 +1,10 @@ using System; using System.Linq; using System.Threading.Tasks; -using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { public class Playlists : VirtualizationListViewModel, ISaveableViewModel, IPlaylistsViewModel { diff --git a/src/Maple/ViewModels/Settings/Culture.cs b/src/Maple.Core/ViewModels/Settings/Culture.cs similarity index 89% rename from src/Maple/ViewModels/Settings/Culture.cs rename to src/Maple.Core/ViewModels/Settings/Culture.cs index 9b502f0..004b6d1 100644 --- a/src/Maple/ViewModels/Settings/Culture.cs +++ b/src/Maple.Core/ViewModels/Settings/Culture.cs @@ -1,7 +1,6 @@ using System.Globalization; -using Maple.Core; -namespace Maple +namespace Maple.Core { public class Culture : BaseViewModel { diff --git a/src/Maple/ViewModels/Settings/Cultures.cs b/src/Maple.Core/ViewModels/Settings/Cultures.cs similarity index 98% rename from src/Maple/ViewModels/Settings/Cultures.cs rename to src/Maple.Core/ViewModels/Settings/Cultures.cs index 2aa2792..f96bc7d 100644 --- a/src/Maple/ViewModels/Settings/Cultures.cs +++ b/src/Maple.Core/ViewModels/Settings/Cultures.cs @@ -1,10 +1,9 @@ using System.Linq; using System.Threading.Tasks; -using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { public class Cultures : BaseListViewModel, ICultureViewModel { diff --git a/src/Maple/ViewModels/Settings/OptionsViewModel.cs b/src/Maple.Core/ViewModels/Settings/OptionsViewModel.cs similarity index 96% rename from src/Maple/ViewModels/Settings/OptionsViewModel.cs rename to src/Maple.Core/ViewModels/Settings/OptionsViewModel.cs index 14d51f7..d16318a 100644 --- a/src/Maple/ViewModels/Settings/OptionsViewModel.cs +++ b/src/Maple.Core/ViewModels/Settings/OptionsViewModel.cs @@ -1,8 +1,7 @@ using System; -using Maple.Core; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { public class OptionsViewModel : ObservableObject { diff --git a/src/Maple/ViewModels/SplashScreenViewModel.cs b/src/Maple.Core/ViewModels/SplashScreenViewModel.cs similarity index 99% rename from src/Maple/ViewModels/SplashScreenViewModel.cs rename to src/Maple.Core/ViewModels/SplashScreenViewModel.cs index 5609d0a..fb17511 100644 --- a/src/Maple/ViewModels/SplashScreenViewModel.cs +++ b/src/Maple.Core/ViewModels/SplashScreenViewModel.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Generic; using System.Windows.Input; -using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { public class SplashScreenViewModel : ObservableObject, ISplashScreenViewModel { diff --git a/src/Maple/ViewModels/StatusbarViewModel.cs b/src/Maple.Core/ViewModels/StatusbarViewModel.cs similarity index 98% rename from src/Maple/ViewModels/StatusbarViewModel.cs rename to src/Maple.Core/ViewModels/StatusbarViewModel.cs index f91b8bc..be1abba 100644 --- a/src/Maple/ViewModels/StatusbarViewModel.cs +++ b/src/Maple.Core/ViewModels/StatusbarViewModel.cs @@ -1,9 +1,8 @@ using System; -using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; -namespace Maple +namespace Maple.Core { public class StatusbarViewModel : ViewModel { diff --git a/src/Maple.Data/Maple.Data.csproj b/src/Maple.Data/Maple.Data.csproj index bea4727..a367c49 100644 --- a/src/Maple.Data/Maple.Data.csproj +++ b/src/Maple.Data/Maple.Data.csproj @@ -50,7 +50,7 @@ - + diff --git a/src/Maple.Test/Maple.Test.csproj b/src/Maple.Test/Maple.Test.csproj index eb633d0..152c684 100644 --- a/src/Maple.Test/Maple.Test.csproj +++ b/src/Maple.Test/Maple.Test.csproj @@ -112,7 +112,7 @@ - 2.12.5 + 2.12.6 1.2.0 diff --git a/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs b/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs index 1a44f6c..9b41e55 100644 --- a/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs +++ b/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading.Tasks; using DryIoc; +using Maple.Core; using Maple.Domain; using Microsoft.VisualStudio.TestTools.UnitTesting; using NSubstitute; diff --git a/src/Maple.Youtube/Maple.Youtube.csproj b/src/Maple.Youtube/Maple.Youtube.csproj index 7343835..8dfb4c2 100644 --- a/src/Maple.Youtube/Maple.Youtube.csproj +++ b/src/Maple.Youtube/Maple.Youtube.csproj @@ -34,7 +34,7 @@ - 1.31.1.1063 + 1.32.0.1079 @@ -68,10 +68,6 @@ - - {21fa5854-0692-42e2-924e-a38cf3c7ff71} - Maple.Core - {9d7d05a6-8271-4836-a7bb-5b2abeccbd81} Maple.Domain diff --git a/src/Maple/Maple.csproj b/src/Maple/Maple.csproj index 7252149..40956d0 100644 --- a/src/Maple/Maple.csproj +++ b/src/Maple/Maple.csproj @@ -60,14 +60,11 @@ ..\Resources\Images\logo.ico - - 2.12.5 + 2.12.6 - - - + 2.2.0 @@ -76,7 +73,7 @@ 2.2.0 - + @@ -85,10 +82,6 @@ 1.7.8 - - - - @@ -120,14 +113,17 @@ Properties\SharedAssemblyInfo.cs - - - - - - - - + + + + + + + + + + + @@ -148,8 +144,6 @@ - - SplashScreen.xaml @@ -159,53 +153,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MediaPlayerPage.xaml @@ -218,17 +170,10 @@ ColorOptionsPage.xaml - - - - - - - - - - - + + MSBuild:Compile + Designer + Designer MSBuild:Compile @@ -257,10 +202,6 @@ Designer MSBuild:Compile - - Designer - MSBuild:Compile - MSBuild:Compile Designer @@ -296,7 +237,7 @@ ResXFileCodeGenerator Resources.Designer.cs - + Resources\client_secret.json PreserveNewest @@ -318,16 +259,6 @@ false - - - Resources\logo.ico - - - - - Resources\logo_withoutbackground.png - - @@ -354,10 +285,16 @@ - + Resources\Art_Of_Escapism_-_Universe_Words.mp3 PreserveNewest + + Resources\logo_withoutbackground.png + + + Resources\logo.ico + diff --git a/src/Maple/Resources/Style.xaml b/src/Maple/Resources/Style.xaml index 2c2b839..a8578a7 100644 --- a/src/Maple/Resources/Style.xaml +++ b/src/Maple/Resources/Style.xaml @@ -966,7 +966,7 @@ - + @@ -986,7 +986,7 @@ - + @@ -1006,18 +1006,18 @@ - + - + - + - + @@ -1109,7 +1109,7 @@ - + @@ -1153,7 +1153,7 @@ - + @@ -1193,14 +1193,14 @@ - + - + diff --git a/src/Maple/Interfaces/IConfigurableWindowSettings.cs b/src/Maple/UI/Base/IConfigurableWindowSettings.cs similarity index 100% rename from src/Maple/Interfaces/IConfigurableWindowSettings.cs rename to src/Maple/UI/Base/IConfigurableWindowSettings.cs diff --git a/src/Maple/Interfaces/IIocFrameworkElement.cs b/src/Maple/UI/Base/IIocFrameworkElement.cs similarity index 100% rename from src/Maple/Interfaces/IIocFrameworkElement.cs rename to src/Maple/UI/Base/IIocFrameworkElement.cs diff --git a/src/Maple/UI/PackIcon.cs b/src/Maple/UI/PackIcon.cs index ab5d6b7..1c0c47d 100644 --- a/src/Maple/UI/PackIcon.cs +++ b/src/Maple/UI/PackIcon.cs @@ -9,7 +9,7 @@ namespace Maple /// /// /// - public class PackIcon : PackIcon + public class PackIcon : PackIconControl { private static IDictionary _cache; /// diff --git a/src/Maple/ViewModels/MediaPlayer/NAudio/PlaybackDeviceFactory.cs b/src/Maple/ViewModels/MediaPlayer/NAudio/PlaybackDeviceFactory.cs index 424e3e1..094b888 100644 --- a/src/Maple/ViewModels/MediaPlayer/NAudio/PlaybackDeviceFactory.cs +++ b/src/Maple/ViewModels/MediaPlayer/NAudio/PlaybackDeviceFactory.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Maple.Core; using Maple.Domain; using NAudio.Wave; diff --git a/src/Maple/ViewModels/Navigation/Scene.cs b/src/Maple/ViewModels/Navigation/Scene.cs index e095499..04c094b 100644 --- a/src/Maple/ViewModels/Navigation/Scene.cs +++ b/src/Maple/ViewModels/Navigation/Scene.cs @@ -6,11 +6,6 @@ namespace Maple { - /// - /// - /// - /// - /// public class Scene : ObservableObject, ISequence { private readonly ILocalizationService _manager; diff --git a/src/Maple/ViewModels/Settings/UIColorsViewModel.cs b/src/Maple/ViewModels/UIColorsViewModel.cs similarity index 100% rename from src/Maple/ViewModels/Settings/UIColorsViewModel.cs rename to src/Maple/ViewModels/UIColorsViewModel.cs From 065d2631b2addd0cc38381ae012b2fcbe44ab03a Mon Sep 17 00:00:00 2001 From: Insire Date: Tue, 9 Jan 2018 20:21:52 +0100 Subject: [PATCH 09/16] removed obsolete references to nuget packages --- .../IO/Util/SelectedTreeViewItemBehavior.cs | 72 ------------------- src/Maple.Core/Maple.Core.csproj | 7 -- src/Maple.Youtube/Maple.Youtube.csproj | 4 ++ .../MrlExtractionService.cs | 0 src/Maple/Maple.csproj | 8 --- 5 files changed, 4 insertions(+), 87 deletions(-) delete mode 100644 src/Maple.Core/IO/Util/SelectedTreeViewItemBehavior.cs rename src/{Maple.Core/Services => Maple.Youtube}/MrlExtractionService.cs (100%) diff --git a/src/Maple.Core/IO/Util/SelectedTreeViewItemBehavior.cs b/src/Maple.Core/IO/Util/SelectedTreeViewItemBehavior.cs deleted file mode 100644 index af7d48c..0000000 --- a/src/Maple.Core/IO/Util/SelectedTreeViewItemBehavior.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.Windows; -using System.Windows.Controls; -using System.Windows.Interactivity; - -namespace Maple.Core -{ - /// - /// - /// - /// - /// - public class SelectedTreeViewItemBehavior : Behavior - { - /// - /// Gets or sets the selected item. - /// - /// - /// The selected item. - /// - /// - public object SelectedItem - { - get { return GetValue(SelectedItemProperty); } - set { SetValue(SelectedItemProperty, value); } - } - - /// - /// The selected item property - /// - /// - public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register( - nameof(SelectedItem), - typeof(object), - typeof(SelectedTreeViewItemBehavior), - new UIPropertyMetadata(null, OnSelectedItemChanged)); - - private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) - { - var item = e.NewValue as TreeViewItem; - - item?.SetValue(TreeViewItem.IsSelectedProperty, true); - } - - /// - /// Called when [attached]. - /// - /// - protected override void OnAttached() - { - base.OnAttached(); - - AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged; - } - - /// - /// Called when [detaching]. - /// - /// - protected override void OnDetaching() - { - base.OnDetaching(); - - if (AssociatedObject != null) - AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged; - } - - private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e) - { - SelectedItem = e.NewValue; - } - } -} diff --git a/src/Maple.Core/Maple.Core.csproj b/src/Maple.Core/Maple.Core.csproj index adf149c..13b6b02 100644 --- a/src/Maple.Core/Maple.Core.csproj +++ b/src/Maple.Core/Maple.Core.csproj @@ -36,8 +36,6 @@ 6.2.2 - - 2.2.0 @@ -46,12 +44,9 @@ 2.2.0 - - 1.7.8 - @@ -123,7 +118,6 @@ - @@ -186,7 +180,6 @@ - diff --git a/src/Maple.Youtube/Maple.Youtube.csproj b/src/Maple.Youtube/Maple.Youtube.csproj index 8dfb4c2..5321469 100644 --- a/src/Maple.Youtube/Maple.Youtube.csproj +++ b/src/Maple.Youtube/Maple.Youtube.csproj @@ -37,6 +37,9 @@ 1.32.0.1079 + + 0.10.11 + @@ -56,6 +59,7 @@ + diff --git a/src/Maple.Core/Services/MrlExtractionService.cs b/src/Maple.Youtube/MrlExtractionService.cs similarity index 100% rename from src/Maple.Core/Services/MrlExtractionService.cs rename to src/Maple.Youtube/MrlExtractionService.cs diff --git a/src/Maple/Maple.csproj b/src/Maple/Maple.csproj index 40956d0..2af8155 100644 --- a/src/Maple/Maple.csproj +++ b/src/Maple/Maple.csproj @@ -66,23 +66,15 @@ - - 2.2.0 - - - 2.2.0 - - 1.7.8 - From e8f93499ac68334ff9863a32379ee8fc7b07ba6e Mon Sep 17 00:00:00 2001 From: Insire Date: Tue, 9 Jan 2018 20:37:27 +0100 Subject: [PATCH 10/16] added basic DataProviders --- src/Maple.Core/Maple.Core.csproj | 9 ++++--- .../Virtualization/Base/BaseDataProvider.cs | 24 +++++++++++-------- .../Virtualization/Base/IDataProvider.cs | 5 ++-- .../Virtualization/VirtualizationViewModel.cs | 11 +++++---- .../{ => DataAccess}/IMediaRepository.cs | 0 .../DataAccess/MediaItemDataProvider.cs | 10 ++++++++ .../DataAccess/MediaPlayerDataProvider.cs | 10 ++++++++ .../{ => DataAccess}/MediaRepository.cs | 0 .../DataAccess/PlaylistDataProvider.cs | 10 ++++++++ .../ViewModelServiceContainer.cs | 0 10 files changed, 59 insertions(+), 20 deletions(-) rename src/Maple.Core/Services/{ => DataAccess}/IMediaRepository.cs (100%) create mode 100644 src/Maple.Core/Services/DataAccess/MediaItemDataProvider.cs create mode 100644 src/Maple.Core/Services/DataAccess/MediaPlayerDataProvider.cs rename src/Maple.Core/Services/{ => DataAccess}/MediaRepository.cs (100%) create mode 100644 src/Maple.Core/Services/DataAccess/PlaylistDataProvider.cs rename src/Maple.Core/{Services => ViewModels}/ViewModelServiceContainer.cs (100%) diff --git a/src/Maple.Core/Maple.Core.csproj b/src/Maple.Core/Maple.Core.csproj index 13b6b02..9d3bf07 100644 --- a/src/Maple.Core/Maple.Core.csproj +++ b/src/Maple.Core/Maple.Core.csproj @@ -109,6 +109,9 @@ + + + @@ -183,15 +186,15 @@ - - + + - + diff --git a/src/Maple.Core/Observables/Virtualization/Base/BaseDataProvider.cs b/src/Maple.Core/Observables/Virtualization/Base/BaseDataProvider.cs index 8566299..e837912 100644 --- a/src/Maple.Core/Observables/Virtualization/Base/BaseDataProvider.cs +++ b/src/Maple.Core/Observables/Virtualization/Base/BaseDataProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using Maple.Localization.Properties; namespace Maple.Core @@ -7,34 +8,37 @@ namespace Maple.Core public abstract class BaseDataProvider : IDataProvider where TViewModel : class { - private readonly IDictionary _cache; - private readonly Func _viewModelFactory; + private readonly ICachingService _cache; + private readonly Func> _viewModelFactory; - protected BaseDataProvider(Func viewModelFactory, IDictionary cache) + protected BaseDataProvider(Func> viewModelFactory, ICachingService cache) { _cache = cache ?? throw new ArgumentNullException(nameof(cache), $"{nameof(cache)} {Resources.IsRequired}"); _viewModelFactory = viewModelFactory ?? throw new ArgumentNullException(nameof(viewModelFactory), $"{nameof(viewModelFactory)} {Resources.IsRequired}"); } - public void Chunk(IEnumerable Ids) + public async Task Chunk(IEnumerable Ids) { foreach (var id in Ids) { - if (_cache.ContainsKey(id)) + if (_cache.Contains(id)) continue; - _cache.Add(id, InternalGet(id)); + _cache.Add(id, await InternalGet(id).ConfigureAwait(false)); } } - public TViewModel Get(TPrimaryKeyType id) + public async Task Get(TPrimaryKeyType key) { - return _cache[id]; + if (_cache.TryGetValue(key, out var result)) + return result; + + return await InternalGet(key).ConfigureAwait(false); } - private TViewModel InternalGet(TPrimaryKeyType id) + private async Task InternalGet(TPrimaryKeyType key) { - return _viewModelFactory(id); + return await _viewModelFactory(key).ConfigureAwait(false); } public void Clear() diff --git a/src/Maple.Core/Observables/Virtualization/Base/IDataProvider.cs b/src/Maple.Core/Observables/Virtualization/Base/IDataProvider.cs index 8f6bd91..be749d4 100644 --- a/src/Maple.Core/Observables/Virtualization/Base/IDataProvider.cs +++ b/src/Maple.Core/Observables/Virtualization/Base/IDataProvider.cs @@ -1,12 +1,13 @@ using System.Collections.Generic; +using System.Threading.Tasks; namespace Maple.Core { public interface IDataProvider { - T Get(TPrimaryKeyType id); + Task Get(TPrimaryKeyType id); - void Chunk(IEnumerable Ids); + Task Chunk(IEnumerable Ids); void Clear(); void Remove(TPrimaryKeyType id); diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs index dd59774..0cfe7d7 100644 --- a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs +++ b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using System.Windows.Input; using Maple.Domain; using Maple.Localization.Properties; @@ -52,8 +53,8 @@ public ICommand DeflateCommand private set { SetValue(ref _deflateCommand, value); } } - private ICommand _expandCommand; - public ICommand ExpandCommand + private IAsyncCommand _expandCommand; + public IAsyncCommand ExpandCommand { get { return _expandCommand; } private set { SetValue(ref _expandCommand, value); } @@ -65,15 +66,15 @@ public VirtualizationViewModel(TKeyDataType id, IDataProvider + { + protected MediaItemDataProvider(IMediaRepository mediaRepository, ICachingService cache) + : base(mediaRepository.GetMediaItemByIdAsync, cache) + { + } + } +} diff --git a/src/Maple.Core/Services/DataAccess/MediaPlayerDataProvider.cs b/src/Maple.Core/Services/DataAccess/MediaPlayerDataProvider.cs new file mode 100644 index 0000000..f9c9ec9 --- /dev/null +++ b/src/Maple.Core/Services/DataAccess/MediaPlayerDataProvider.cs @@ -0,0 +1,10 @@ +namespace Maple.Core +{ + public class MediaPlayerDataProvider : BaseDataProvider + { + protected MediaPlayerDataProvider(IMediaRepository mediaRepository, ICachingService cache) + : base(mediaRepository.GetMediaPlayerByIdAsync, cache) + { + } + } +} diff --git a/src/Maple.Core/Services/MediaRepository.cs b/src/Maple.Core/Services/DataAccess/MediaRepository.cs similarity index 100% rename from src/Maple.Core/Services/MediaRepository.cs rename to src/Maple.Core/Services/DataAccess/MediaRepository.cs diff --git a/src/Maple.Core/Services/DataAccess/PlaylistDataProvider.cs b/src/Maple.Core/Services/DataAccess/PlaylistDataProvider.cs new file mode 100644 index 0000000..86b3cc9 --- /dev/null +++ b/src/Maple.Core/Services/DataAccess/PlaylistDataProvider.cs @@ -0,0 +1,10 @@ +namespace Maple.Core +{ + public class PlaylistDataProvider : BaseDataProvider + { + protected PlaylistDataProvider(IMediaRepository mediaRepository, ICachingService cache) + : base(mediaRepository.GetPlaylistByIdAsync, cache) + { + } + } +} diff --git a/src/Maple.Core/Services/ViewModelServiceContainer.cs b/src/Maple.Core/ViewModels/ViewModelServiceContainer.cs similarity index 100% rename from src/Maple.Core/Services/ViewModelServiceContainer.cs rename to src/Maple.Core/ViewModels/ViewModelServiceContainer.cs From 3fd72cf13224c89b7b04581556f8204834870366 Mon Sep 17 00:00:00 2001 From: Peter Vietense Date: Tue, 23 Jan 2018 23:36:23 +0100 Subject: [PATCH 11/16] wip --- Maple.sln | 3 +- NuGet.Config | 22 +++++++ src/Maple.Core/Maple.Core.csproj | 11 ++-- .../Observables/Base/ILoadableViewModel.cs | 8 ++- .../ViewModels/BaseDataListViewModel.cs | 53 ++++++++++------ .../ViewModels/BaseListViewModel.cs | 13 ---- .../ValidableBaseDataListViewModel.cs | 2 +- .../Observables/ViewModels/ViewModel.cs | 1 + ...wModel.cs => IVirtualizedListViewModel.cs} | 2 +- .../VirtualizationListViewModel.cs | 60 ------------------- .../Virtualization/VirtualizationViewModel.cs | 2 +- ...cs => VirtualizingCollectionViewSource.cs} | 17 +++--- .../Services/Caching/MemoryCacheService.cs | 4 +- .../DataAccess}/Base/BaseDataProvider.cs | 0 .../DataAccess}/Base/IDataProvider.cs | 0 .../DataAccess/{ => Base}/IMediaRepository.cs | 0 .../ViewModels/MediaItems/MediaItems.cs | 4 +- .../ViewModels/MediaPlayer/MediaPlayers.cs | 2 +- .../ViewModels/Playlists/Playlist.cs | 7 +-- .../ViewModels/Playlists/Playlists.cs | 4 +- .../ViewModels/Settings/Cultures.cs | 6 +- .../ViewModels/ViewModelServiceContainer.cs | 9 ++- .../Interfaces/IRangeObservableCollection.cs | 3 +- .../ViewModels/Playlists/PlaylistsTests.cs | 2 +- src/Maple/App.xaml.cs | 2 +- src/Maple/UI/Base/SharedResourceDictionary.cs | 15 ++++- src/Maple/ViewModels/ShellViewModel.cs | 57 ------------------ src/Maple/ViewModels/UIColorsViewModel.cs | 2 +- src/Resources/SharedAssemblyInfo.cs | 2 +- 29 files changed, 119 insertions(+), 194 deletions(-) create mode 100644 NuGet.Config rename src/Maple.Core/Observables/Virtualization/Base/{IVirtualizedViewModel.cs => IVirtualizedListViewModel.cs} (78%) delete mode 100644 src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs rename src/Maple.Core/Observables/Virtualization/{DataVirtualizationCollectionView.cs => VirtualizingCollectionViewSource.cs} (74%) rename src/Maple.Core/{Observables/Virtualization => Services/DataAccess}/Base/BaseDataProvider.cs (100%) rename src/Maple.Core/{Observables/Virtualization => Services/DataAccess}/Base/IDataProvider.cs (100%) rename src/Maple.Core/Services/DataAccess/{ => Base}/IMediaRepository.cs (100%) diff --git a/Maple.sln b/Maple.sln index a9926ba..ebbd199 100644 --- a/Maple.sln +++ b/Maple.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27130.2010 +VisualStudioVersion = 15.0.27130.2024 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D65C950A-327A-496D-A49C-B45E8F97C610}" ProjectSection(SolutionItems) = preProject @@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .XamlStyler = .XamlStyler src\Resources\Art_Of_Escapism_-_Universe_Words.mp3 = src\Resources\Art_Of_Escapism_-_Universe_Words.mp3 src\Resources\client_secret.json = src\Resources\client_secret.json + NuGet.Config = NuGet.Config src\Resources\SharedAssemblyInfo.cs = src\Resources\SharedAssemblyInfo.cs EndProjectSection EndProject diff --git a/NuGet.Config b/NuGet.Config new file mode 100644 index 0000000..1d70b0d --- /dev/null +++ b/NuGet.Config @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Maple.Core/Maple.Core.csproj b/src/Maple.Core/Maple.Core.csproj index 9d3bf07..93b6a0e 100644 --- a/src/Maple.Core/Maple.Core.csproj +++ b/src/Maple.Core/Maple.Core.csproj @@ -108,6 +108,8 @@ + + @@ -133,11 +135,8 @@ - - - - - + + @@ -186,7 +185,7 @@ - + diff --git a/src/Maple.Core/Observables/Base/ILoadableViewModel.cs b/src/Maple.Core/Observables/Base/ILoadableViewModel.cs index 205f904..fc150cd 100644 --- a/src/Maple.Core/Observables/Base/ILoadableViewModel.cs +++ b/src/Maple.Core/Observables/Base/ILoadableViewModel.cs @@ -2,6 +2,12 @@ namespace Maple.Core { + public interface ILoadableViewModel : ILoadableViewModel + { + Task GetCountAsync(); + Task GetItemsWithKey(TKey[] keys); + } + public interface ILoadableViewModel { /// @@ -14,7 +20,5 @@ public interface ILoadableViewModel IAsyncCommand LoadCommand { get; } IAsyncCommand RefreshCommand { get; } - - Task LoadAsync(); } } diff --git a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs index b70d382..d847f0c 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Threading.Tasks; using Maple.Domain; @@ -8,16 +9,14 @@ namespace Maple.Core { - /// - /// ListViewModel implementation for ObservableObjects related to the DataAccessLayer (DB) - /// - /// a wrapper class implementing - /// a DTO implementing - /// - public abstract class BaseDataListViewModel : BaseListViewModel, ILoadableViewModel, ISaveableViewModel - where TViewModel : BaseDataViewModel, ISequence + // TODO add virtualization here + // + public abstract class BaseDataListViewModel : BaseListViewModel, ILoadableViewModel, ISaveableViewModel + where TViewModel : VirtualizationViewModel, ISequence where TModel : class, IBaseModel { + private readonly IMapleRepository _repository; + protected readonly ISequenceService _sequenceProvider; protected readonly ILocalizationService _translationService; protected readonly ILoggingService _log; @@ -28,32 +27,50 @@ public abstract class BaseDataListViewModel : public abstract IAsyncCommand LoadCommand { get; } public abstract IAsyncCommand RefreshCommand { get; } - public abstract Task LoadAsync(); + public abstract Task GetCountAsync(); public abstract Task SaveAsync(); + public abstract Task GetItemsWithKey(TKeyDataType[] keys); + + private ICollectionView _view; + /// + /// For grouping, sorting and filtering + /// + /// + /// The view. + /// + public ICollectionView View + { + get { return _view; } + protected set { SetValue(ref _view, value); } + } - protected BaseDataListViewModel(ViewModelServiceContainer container) + protected BaseDataListViewModel(ViewModelServiceContainer container, IMapleRepository repository) : base(container.Messenger) { + _repository = repository ?? throw new ArgumentNullException(nameof(repository), $"{nameof(repository)} {Resources.IsRequired}"); + _log = container.Log; _translationService = container.LocalizationService; _sequenceProvider = container.SequenceService; + + View = new VirtualizingCollectionViewSource(container, (IList)_items); } /// /// Removes the specified item. /// /// The item. - public override void Remove(TViewModel viewModel) + public override void Remove(TViewModel container) { - if (viewModel == null) - throw new ArgumentNullException(nameof(viewModel), $"{nameof(viewModel)} {Resources.IsRequired}"); + if (container == null) + throw new ArgumentNullException(nameof(container), $"{nameof(container)} {Resources.IsRequired}"); using (BusyStack.GetToken()) { - while (Items.Contains(viewModel)) + while (Items.Contains(container)) { - viewModel.Model.IsDeleted = true; - base.Remove(viewModel); + container.ViewModel.Model.IsDeleted = true; + base.Remove(container); } } } @@ -69,7 +86,7 @@ public override void RemoveRange(IEnumerable items) using (BusyStack.GetToken()) { - items.ForEach(p => p.Model.IsDeleted = true); + items.ForEach(p => p.ViewModel.Model.IsDeleted = true); base.RemoveRange(items); } } @@ -124,7 +141,5 @@ public override void AddRange(IEnumerable items) SelectedItem = Items.First(); } } - - } } diff --git a/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs index b424f79..c83bdd3 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs @@ -45,19 +45,6 @@ public IReadOnlyCollection Items protected set { SetValue(ref _items, (IRangeObservableCollection)value); } } - private ICollectionView _view; - /// - /// For grouping, sorting and filtering - /// - /// - /// The view. - /// - public ICollectionView View - { - get { return _view; } - protected set { SetValue(ref _view, value); } - } - /// /// Gets the at the specified index. /// diff --git a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs index aee0ba2..c0fa735 100644 --- a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs @@ -3,7 +3,7 @@ namespace Maple.Core { public abstract class ValidableBaseDataListViewModel : BaseDataListViewModel - where TViewModel : BaseDataViewModel, ISequence + where TViewModel : VirtualizationViewModel, ISequence where TModel : class, IBaseModel { protected ValidableBaseDataListViewModel(ViewModelServiceContainer container) diff --git a/src/Maple.Core/Observables/ViewModels/ViewModel.cs b/src/Maple.Core/Observables/ViewModels/ViewModel.cs index cc473f4..99a892c 100644 --- a/src/Maple.Core/Observables/ViewModels/ViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/ViewModel.cs @@ -6,6 +6,7 @@ namespace Maple.Core { public abstract class ViewModel : ObservableObject, IDisposable { + // TODO cache equality comparer protected IMessenger Messenger { get; } protected BusyStack BusyStack { get; } diff --git a/src/Maple.Core/Observables/Virtualization/Base/IVirtualizedViewModel.cs b/src/Maple.Core/Observables/Virtualization/Base/IVirtualizedListViewModel.cs similarity index 78% rename from src/Maple.Core/Observables/Virtualization/Base/IVirtualizedViewModel.cs rename to src/Maple.Core/Observables/Virtualization/Base/IVirtualizedListViewModel.cs index b8c5213..39ccd74 100644 --- a/src/Maple.Core/Observables/Virtualization/Base/IVirtualizedViewModel.cs +++ b/src/Maple.Core/Observables/Virtualization/Base/IVirtualizedListViewModel.cs @@ -2,7 +2,7 @@ namespace Maple.Core { - public interface IVirtualizedViewModel + public interface IVirtualizedListViewModel { void ExtendItems(IEnumerable items); void DeflateItem(object item); diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs b/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs deleted file mode 100644 index c09e1fd..0000000 --- a/src/Maple.Core/Observables/Virtualization/VirtualizationListViewModel.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using Maple.Domain; - -namespace Maple.Core -{ - public abstract class VirtualizationListViewModel : ValidableBaseDataListViewModel, IVirtualizedViewModel, ILoadableViewModel, ISaveableViewModel - where TViewModel : BaseDataViewModel, ISequence - where TModel : class, IBaseModel - { - private bool _isLoaded; - /// - /// Indicates whether the LoadCommand/ the Load Method has been executed yet - /// - public override bool IsLoaded - { - get { return _isLoaded; } - protected set - { - if (value) - SetValue(ref _isLoaded, value, OnChanged: () => Messenger.Publish(new LoadedMessage(this, this))); - } - } - - public int Count => Items?.Count ?? 0; - - public override IAsyncCommand LoadCommand => AsyncCommand.Create(LoadAsync, () => !IsLoaded); - public override IAsyncCommand RefreshCommand => AsyncCommand.Create(LoadAsync, () => IsLoaded); - public override IAsyncCommand SaveCommand => AsyncCommand.Create(SaveAsync); - - protected VirtualizationListViewModel(ViewModelServiceContainer container) - : base(container) - { - var items = new RangeObservableCollection(); - items.CollectionChanged += ItemsCollectionChanged; - Items = items; - - View = new VirtualizingCollectionViewSource(items); - - // initial Notification, so that UI recognizes the value - OnPropertyChanged(nameof(Count)); - } - - public void DeflateItem(object item) - { - throw new NotImplementedException(); - } - - public void ExtendItems(IEnumerable items) - { - throw new NotImplementedException(); - } - - private void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) - { - OnPropertyChanged(nameof(Count)); - } - } -} diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs index 0cfe7d7..397888f 100644 --- a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs +++ b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs @@ -6,7 +6,7 @@ namespace Maple.Core { - public sealed class VirtualizationViewModel : ObservableObject + public class VirtualizationViewModel : ObservableObject where TModel : class, IBaseModel { private readonly IDataProvider, TKeyDataType> _dataProvider; diff --git a/src/Maple.Core/Observables/Virtualization/DataVirtualizationCollectionView.cs b/src/Maple.Core/Observables/Virtualization/VirtualizingCollectionViewSource.cs similarity index 74% rename from src/Maple.Core/Observables/Virtualization/DataVirtualizationCollectionView.cs rename to src/Maple.Core/Observables/Virtualization/VirtualizingCollectionViewSource.cs index 694dbc1..13ca4b4 100644 --- a/src/Maple.Core/Observables/Virtualization/DataVirtualizationCollectionView.cs +++ b/src/Maple.Core/Observables/Virtualization/VirtualizingCollectionViewSource.cs @@ -4,30 +4,27 @@ using System.Runtime.Caching; using System.Windows.Data; using System.Windows.Threading; +using Maple.Localization.Properties; namespace Maple.Core { public class VirtualizingCollectionViewSource : ListCollectionView { - private readonly IVirtualizedViewModel _sponsor; + private readonly IVirtualizedListViewModel _sponsor; private readonly HashSet _deferredItems; private readonly MemoryCache _cache; private readonly CacheItemPolicy _policy; private bool _isDeferred; - public VirtualizingCollectionViewSource(IList list) + public VirtualizingCollectionViewSource(ViewModelServiceContainer container, IList list) : base(list) { + _cache = container.Cache ?? throw new ArgumentNullException(nameof(container.Cache), $"{nameof(container.Cache)} {Resources.IsRequired}"); + _policy = container.CacheItemPolicy ?? throw new ArgumentNullException(nameof(container.CacheItemPolicy), $"{nameof(container.CacheItemPolicy)} {Resources.IsRequired}"); + _deferredItems = new HashSet(); - _sponsor = list as IVirtualizedViewModel; - _cache = new MemoryCache(nameof(VirtualizingCollectionViewSource)); - _policy = new CacheItemPolicy() - { - SlidingExpiration = TimeSpan.FromSeconds(3), - Priority = CacheItemPriority.Default, - RemovedCallback = new CacheEntryRemovedCallback(CacheRemovedCallback) - }; + _sponsor = list as IVirtualizedListViewModel; } public void CacheRemovedCallback(CacheEntryRemovedArguments arguments) diff --git a/src/Maple.Core/Services/Caching/MemoryCacheService.cs b/src/Maple.Core/Services/Caching/MemoryCacheService.cs index fe10882..6303cdd 100644 --- a/src/Maple.Core/Services/Caching/MemoryCacheService.cs +++ b/src/Maple.Core/Services/Caching/MemoryCacheService.cs @@ -12,7 +12,7 @@ public abstract class MemoryCacheService : ICachingService _trackedEntries; private readonly MemoryCache _cache; private readonly CacheItemPolicy _policy; - private readonly IVirtualizedViewModel _virtualizationProvider; + private readonly IVirtualizedListViewModel _virtualizationProvider; private readonly string _cacheKeyPart; private MemoryCacheService() @@ -27,7 +27,7 @@ private MemoryCacheService() }; } - protected MemoryCacheService(MemoryCache cache, IVirtualizedViewModel virtualizationProvider) + protected MemoryCacheService(MemoryCache cache, IVirtualizedListViewModel virtualizationProvider) : this() { _virtualizationProvider = virtualizationProvider ?? throw new ArgumentNullException(nameof(virtualizationProvider), $"{nameof(virtualizationProvider)} {Resources.IsRequired}"); diff --git a/src/Maple.Core/Observables/Virtualization/Base/BaseDataProvider.cs b/src/Maple.Core/Services/DataAccess/Base/BaseDataProvider.cs similarity index 100% rename from src/Maple.Core/Observables/Virtualization/Base/BaseDataProvider.cs rename to src/Maple.Core/Services/DataAccess/Base/BaseDataProvider.cs diff --git a/src/Maple.Core/Observables/Virtualization/Base/IDataProvider.cs b/src/Maple.Core/Services/DataAccess/Base/IDataProvider.cs similarity index 100% rename from src/Maple.Core/Observables/Virtualization/Base/IDataProvider.cs rename to src/Maple.Core/Services/DataAccess/Base/IDataProvider.cs diff --git a/src/Maple.Core/Services/DataAccess/IMediaRepository.cs b/src/Maple.Core/Services/DataAccess/Base/IMediaRepository.cs similarity index 100% rename from src/Maple.Core/Services/DataAccess/IMediaRepository.cs rename to src/Maple.Core/Services/DataAccess/Base/IMediaRepository.cs diff --git a/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs b/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs index 2b29571..485aaa8 100644 --- a/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs +++ b/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs @@ -6,7 +6,7 @@ namespace Maple.Core { - public class MediaItems : VirtualizationListViewModel, IMediaItemsViewModel + public class MediaItems : ValidableBaseDataListViewModel, IMediaItemsViewModel { private readonly Func _repositoryFactory; private readonly IMediaItemMapper _mediaItemMapper; @@ -24,7 +24,7 @@ public void Add(Playlist playlist) Add(_mediaItemMapper.GetNewMediaItem(sequence, playlist)); } - public override async Task LoadAsync() + public override async Task GetCountAsync() { _log.Info($"{_translationService.Translate(nameof(Resources.Loading))} {_translationService.Translate(nameof(Resources.MediaItems))}"); Clear(); diff --git a/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs index 582a2b3..194b263 100644 --- a/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs +++ b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs @@ -76,7 +76,7 @@ public override async Task SaveAsync() } } - public override async Task LoadAsync() + public override async Task GetCountAsync() { _notificationService.Info($"{_translationService.Translate(nameof(Resources.Loading))} {_translationService.Translate(nameof(Resources.MediaPlayers))}"); Clear(); diff --git a/src/Maple.Core/ViewModels/Playlists/Playlist.cs b/src/Maple.Core/ViewModels/Playlists/Playlist.cs index 03448dd..78a98cf 100644 --- a/src/Maple.Core/ViewModels/Playlists/Playlist.cs +++ b/src/Maple.Core/ViewModels/Playlists/Playlist.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using System.Windows.Data; using System.Windows.Input; using FluentValidation; using Maple.Core; @@ -175,14 +174,13 @@ public Playlist(ViewModelServiceContainer container, IValidator valida _isShuffeling = model.IsShuffeling; _sequence = model.Sequence; - RepeatModes = new RangeObservableCollection(Enum.GetValues(typeof(RepeatMode)).Cast().ToList()); _history = new Stack(); + RepeatModes = new RangeObservableCollection(Enum.GetValues(typeof(RepeatMode)).Cast().ToList()); Items = new RangeObservableCollection(); _items.CollectionChanged += (o, e) => OnPropertyChanged(nameof(Count)); - BindingOperations.EnableCollectionSynchronization(Items, _itemsLock); - View = CollectionViewSource.GetDefaultView(Items); // TODO add sorting by sequence + View = new VirtualizingCollectionViewSource(container, (IList)_items); OnPropertyChanged(nameof(Count)); LoadFromFileCommand = AsyncCommand.Create(LoadFromFile, () => CanLoadFromFile()); @@ -199,6 +197,7 @@ public Playlist(ViewModelServiceContainer container, IValidator valida Validate(); } + SkipChangeTracking = false; } diff --git a/src/Maple.Core/ViewModels/Playlists/Playlists.cs b/src/Maple.Core/ViewModels/Playlists/Playlists.cs index cdaa8e3..c6e26c1 100644 --- a/src/Maple.Core/ViewModels/Playlists/Playlists.cs +++ b/src/Maple.Core/ViewModels/Playlists/Playlists.cs @@ -6,7 +6,7 @@ namespace Maple.Core { - public class Playlists : VirtualizationListViewModel, ISaveableViewModel, IPlaylistsViewModel + public class Playlists : ValidableBaseDataListViewModel, ISaveableViewModel, IPlaylistsViewModel { private readonly Func _repositoryFactory; private readonly IPlaylistMapper _playlistMapper; @@ -39,7 +39,7 @@ public override async Task SaveAsync() } } - public override async Task LoadAsync() + public override async Task GetCountAsync() { _log.Info($"{_translationService.Translate(nameof(Resources.Loading))} {_translationService.Translate(nameof(Resources.Playlists))}"); Clear(); diff --git a/src/Maple.Core/ViewModels/Settings/Cultures.cs b/src/Maple.Core/ViewModels/Settings/Cultures.cs index f96bc7d..13792ee 100644 --- a/src/Maple.Core/ViewModels/Settings/Cultures.cs +++ b/src/Maple.Core/ViewModels/Settings/Cultures.cs @@ -10,8 +10,8 @@ public class Cultures : BaseListViewModel, ICultureViewModel private readonly ILocalizationService _manager; private readonly ILoggingService _log; - public IAsyncCommand RefreshCommand => AsyncCommand.Create(LoadAsync); - public IAsyncCommand LoadCommand => AsyncCommand.Create(LoadAsync, () => !IsLoaded); + public IAsyncCommand RefreshCommand => AsyncCommand.Create(GetCountAsync); + public IAsyncCommand LoadCommand => AsyncCommand.Create(GetCountAsync, () => !IsLoaded); public IAsyncCommand SaveCommand => AsyncCommand.Create(Save); private bool _isLoaded; @@ -59,7 +59,7 @@ public Task SaveAsync() }); } - public async Task LoadAsync() + public async Task GetCountAsync() { _log.Info($"{Resources.Loading} {Resources.Options}"); await _manager.LoadAsync().ConfigureAwait(true); diff --git a/src/Maple.Core/ViewModels/ViewModelServiceContainer.cs b/src/Maple.Core/ViewModels/ViewModelServiceContainer.cs index 8612b20..c047d07 100644 --- a/src/Maple.Core/ViewModels/ViewModelServiceContainer.cs +++ b/src/Maple.Core/ViewModels/ViewModelServiceContainer.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.Caching; using Maple.Domain; using Maple.Localization.Properties; @@ -11,14 +12,20 @@ public class ViewModelServiceContainer public ISequenceService SequenceService { get; } public IMessenger Messenger { get; } public ILoggingService Log { get; } + public MemoryCache Cache { get; } + public CacheItemPolicy CacheItemPolicy { get; } - public ViewModelServiceContainer(ILoggingService log, ILoggingNotifcationService notificationService, ILocalizationService localizationService, IMessenger messenger, ISequenceService sequenceService) + public ViewModelServiceContainer(ILoggingService log, + ILoggingNotifcationService notificationService, ILocalizationService localizationService, + IMessenger messenger, ISequenceService sequenceService, MemoryCache cache, CacheItemPolicy itemPolicy) { Log = log ?? throw new ArgumentNullException(nameof(log), $"{nameof(log)} {Resources.IsRequired}"); LocalizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService), $"{nameof(localizationService)} {Resources.IsRequired}"); SequenceService = sequenceService ?? throw new ArgumentNullException(nameof(sequenceService), $"{nameof(sequenceService)} {Resources.IsRequired}"); Messenger = messenger ?? throw new ArgumentNullException(nameof(messenger), $"{nameof(messenger)} {Resources.IsRequired}"); NotificationService = notificationService ?? throw new ArgumentNullException(nameof(notificationService), $"{nameof(notificationService)} {Resources.IsRequired}"); + Cache = cache ?? throw new ArgumentNullException(nameof(cache), $"{nameof(cache)} {Resources.IsRequired}"); + CacheItemPolicy = itemPolicy ?? throw new ArgumentNullException(nameof(itemPolicy), $"{nameof(itemPolicy)} {Resources.IsRequired}"); } } } diff --git a/src/Maple.Domain/Interfaces/IRangeObservableCollection.cs b/src/Maple.Domain/Interfaces/IRangeObservableCollection.cs index fc425b8..bdb627f 100644 --- a/src/Maple.Domain/Interfaces/IRangeObservableCollection.cs +++ b/src/Maple.Domain/Interfaces/IRangeObservableCollection.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System.Collections; +using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Runtime.CompilerServices; diff --git a/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs b/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs index 9b41e55..0f8bd7e 100644 --- a/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs +++ b/src/Maple.Test/ViewModels/Playlists/PlaylistsTests.cs @@ -125,7 +125,7 @@ public async Task Playlists_ShouldLoad() var playlists = (Playlists)container.Resolve(); repository.ClearReceivedCalls(); - await playlists.LoadAsync().ConfigureAwait(false); + await playlists.GetCountAsync().ConfigureAwait(false); await repository.Received(1).GetPlaylistsAsync().ConfigureAwait(false); repository.Received(1).Dispose(); diff --git a/src/Maple/App.xaml.cs b/src/Maple/App.xaml.cs index 64d34e9..b2e5b0e 100644 --- a/src/Maple/App.xaml.cs +++ b/src/Maple/App.xaml.cs @@ -159,7 +159,7 @@ private async Task LoadUpdates(ILoggingService log) private IList LoadApplicationData() { - return new List((_container.Resolve>()).ToArray().Select(p => p.LoadAsync())); + return new List((_container.Resolve>()).ToArray().Select(p => p.GetCountAsync())); } private async Task SaveState() diff --git a/src/Maple/UI/Base/SharedResourceDictionary.cs b/src/Maple/UI/Base/SharedResourceDictionary.cs index b4b8e84..29a4358 100644 --- a/src/Maple/UI/Base/SharedResourceDictionary.cs +++ b/src/Maple/UI/Base/SharedResourceDictionary.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Windows; namespace Maple @@ -11,7 +13,7 @@ namespace Maple /// is created, it only merges the resources from the cache. /// /// - public class SharedResourceDictionary : ResourceDictionary + public class SharedResourceDictionary : ResourceDictionary, INotifyPropertyChanged { /// /// Internal cache of loaded dictionaries @@ -23,6 +25,8 @@ public class SharedResourceDictionary : ResourceDictionary /// private Uri _sourceUri; + public event PropertyChangedEventHandler PropertyChanged; + /// /// Gets or sets the uniform resource identifier (URI) to load resources from. /// @@ -32,6 +36,7 @@ public class SharedResourceDictionary : ResourceDictionary set { _sourceUri = value; + OnPropertyChanged(nameof(Source)); if (!_sharedDictionaries.ContainsKey(value)) { @@ -43,11 +48,15 @@ public class SharedResourceDictionary : ResourceDictionary _sharedDictionaries.Add(value, this); } else - { + // If the dictionary is already loaded, get it from the cache MergedDictionaries.Add(_sharedDictionaries[value]); - } } } + + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } } } diff --git a/src/Maple/ViewModels/ShellViewModel.cs b/src/Maple/ViewModels/ShellViewModel.cs index 1da8769..f4e21f1 100644 --- a/src/Maple/ViewModels/ShellViewModel.cs +++ b/src/Maple/ViewModels/ShellViewModel.cs @@ -4,19 +4,9 @@ namespace Maple { - /// - /// - /// - /// public class ShellViewModel : ObservableObject { private StatusbarViewModel _statusbarViewModel; - /// - /// Gets the statusbar view model. - /// - /// - /// The statusbar view model. - /// public StatusbarViewModel StatusbarViewModel { get { return _statusbarViewModel; } @@ -24,12 +14,6 @@ public StatusbarViewModel StatusbarViewModel } private Scenes _scenes; - /// - /// Gets the scenes. - /// - /// - /// The scenes. - /// public Scenes Scenes { get { return _scenes; } @@ -37,12 +21,6 @@ public Scenes Scenes } private ILocalizationService _translationManager; - /// - /// Gets the translation manager. - /// - /// - /// The translation manager. - /// public ILocalizationService TranslationManager { get { return _translationManager; } @@ -50,12 +28,6 @@ public ILocalizationService TranslationManager } private IDialogViewModel _dialogViewModel; - /// - /// Gets the dialog view model. - /// - /// - /// The dialog view model. - /// public IDialogViewModel DialogViewModel { get { return _dialogViewModel; } @@ -63,12 +35,6 @@ public IDialogViewModel DialogViewModel } private IPlaylistsViewModel _playlists; - /// - /// Gets the playlists. - /// - /// - /// The playlists. - /// public IPlaylistsViewModel Playlists { get { return _playlists; } @@ -76,12 +42,6 @@ public IPlaylistsViewModel Playlists } private IMediaPlayersViewModel _mediaPlayers; - /// - /// Gets the media players. - /// - /// - /// The media players. - /// public IMediaPlayersViewModel MediaPlayers { get { return _mediaPlayers; } @@ -89,29 +49,12 @@ public IMediaPlayersViewModel MediaPlayers } private OptionsViewModel _optionsViewModel; - /// - /// Gets the options view model. - /// - /// - /// The options view model. - /// public OptionsViewModel OptionsViewModel { get { return _optionsViewModel; } private set { SetValue(ref _optionsViewModel, value); } } - /// - /// Initializes a new instance of the class. - /// - /// The translation manager. - /// The scenes. - /// The status bar view model. - /// The dialog view model. - /// The playlists. - /// The media players. - /// The UI colors view model. - /// The options view model. public ShellViewModel(ILocalizationService translationManager, Scenes scenes, StatusbarViewModel statusBarViewModel, diff --git a/src/Maple/ViewModels/UIColorsViewModel.cs b/src/Maple/ViewModels/UIColorsViewModel.cs index 26f9a68..5c570d8 100644 --- a/src/Maple/ViewModels/UIColorsViewModel.cs +++ b/src/Maple/ViewModels/UIColorsViewModel.cs @@ -205,7 +205,7 @@ public async Task SaveAsync() await Save().ConfigureAwait(true); } - public Task LoadAsync() + public Task GetCountAsync() { Load(); return Task.CompletedTask; diff --git a/src/Resources/SharedAssemblyInfo.cs b/src/Resources/SharedAssemblyInfo.cs index 4c15a37..03f02a4 100644 --- a/src/Resources/SharedAssemblyInfo.cs +++ b/src/Resources/SharedAssemblyInfo.cs @@ -11,7 +11,7 @@ [assembly: AssemblyVersion("0.0.1")] [assembly: AssemblyFileVersion("0.0.1")] [assembly: AssemblyInformationalVersion("0.0.0.1")] -[assembly: AssemblyCopyright("© 2017 Insire")] +[assembly: AssemblyCopyright("© 2018 Insire")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] From 2bfaf248e6b62c66eceaf4376647f7e2b2517397 Mon Sep 17 00:00:00 2001 From: Peter Vietense Date: Tue, 13 Feb 2018 18:44:27 +0100 Subject: [PATCH 12/16] wip --- Cake/build.cake | 6 +- NuGet.Config | 18 ++-- .../ViewModels/BaseDataListViewModel.cs | 2 +- .../ViewModels/BaseListViewModel.cs | 22 ++--- .../ValidableBaseDataListViewModel.cs | 4 +- src/Maple.Core/Services/SquirrelLogger.cs | 3 - .../Interfaces/IMediaItemsViewModel.cs | 2 +- .../Interfaces/IMediaPlayersViewModel.cs | 2 +- .../ViewModels/MediaItems/MediaItems.cs | 68 ++++++++----- .../ViewModels/MediaPlayer/MediaPlayers.cs | 96 ++++++++++--------- .../ViewModels/Playlists/Playlists.cs | 83 ++++++++++------ 11 files changed, 177 insertions(+), 129 deletions(-) diff --git a/Cake/build.cake b/Cake/build.cake index 047b2ed..b588e49 100644 --- a/Cake/build.cake +++ b/Cake/build.cake @@ -141,7 +141,8 @@ Task(CleanSolutionTask) var customProject = ParseProject(project.Path, configuration: Configuration, platform: Platform); - CleanDirectory(customProject.OutputPath.FullPath); + foreach(var dir in customProject.OutputPaths) + CleanDirectory(dir); if(customProject.OutputType != "Library") // WinExe continue; @@ -149,7 +150,8 @@ Task(CleanSolutionTask) if(!project.Name.Contains("Test")) // we only care about test assemblies continue; - testsDirectories.Add(customProject.OutputPath.FullPath); + foreach(var dir in customProject.OutputPaths) + testsDirectories.Add(dir.FullPath); } }); diff --git a/NuGet.Config b/NuGet.Config index 1d70b0d..17290f9 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -1,22 +1,20 @@ - + - - - + + + + + + - - - - + \ No newline at end of file diff --git a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs index d847f0c..941f1ce 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs @@ -53,7 +53,7 @@ protected BaseDataListViewModel(ViewModelServiceContainer container, IMapleRepos _translationService = container.LocalizationService; _sequenceProvider = container.SequenceService; - View = new VirtualizingCollectionViewSource(container, (IList)_items); + View = new VirtualizingCollectionViewSource(container, _items); } /// diff --git a/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs index c83bdd3..ad1f822 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.Linq; using System.Windows.Input; -using Maple.Domain; namespace Maple.Core { @@ -18,31 +17,26 @@ public abstract class BaseListViewModel : ViewModel where TViewModel : INotifyPropertyChanged { private TViewModel _selectedItem; - public virtual TViewModel SelectedItem + public TViewModel SelectedItem { get { return _selectedItem; } set { - if (EqualityComparer.Default.Equals(_selectedItem, value)) - return; - - Messenger.Publish(new ViewModelSelectionChangingMessage(Items, _selectedItem)); - _selectedItem = value; - Messenger.Publish(new ViewModelSelectionChangedMessage(Items, _selectedItem)); - - OnPropertyChanged(); + SetValue(ref _selectedItem, value, + () => Messenger.Publish(new ViewModelSelectionChangingMessage(Items, _selectedItem)), + () => Messenger.Publish(new ViewModelSelectionChangedMessage(Items, _selectedItem))); } } - private IRangeObservableCollection _items; + protected RangeObservableCollection _items; /// /// Contains all the UI relevant Models and notifies about changes in the collection and inside the Models themself /// [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] - public IReadOnlyCollection Items + public IReadOnlyList Items { - get { return (IReadOnlyCollection)_items; } - protected set { SetValue(ref _items, (IRangeObservableCollection)value); } + get { return _items; } + protected set { SetValue(ref _items, (RangeObservableCollection)value); } } /// diff --git a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs index c0fa735..adc56ce 100644 --- a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs @@ -6,8 +6,8 @@ public abstract class ValidableBaseDataListViewModel, ISequence where TModel : class, IBaseModel { - protected ValidableBaseDataListViewModel(ViewModelServiceContainer container) - : base(container) + protected ValidableBaseDataListViewModel(ViewModelServiceContainer container, IMapleRepository repository) + : base(container, repository) { } diff --git a/src/Maple.Core/Services/SquirrelLogger.cs b/src/Maple.Core/Services/SquirrelLogger.cs index 05522d3..952143c 100644 --- a/src/Maple.Core/Services/SquirrelLogger.cs +++ b/src/Maple.Core/Services/SquirrelLogger.cs @@ -2,7 +2,6 @@ using System.ComponentModel; using Maple.Domain; using Maple.Localization.Properties; -using Splat; namespace Maple { @@ -13,8 +12,6 @@ public class SquirrelLogger : Splat.ILogger, ILoggingService { private readonly ILoggingService _log; - public LogLevel Level { get; set; } - public SquirrelLogger(ILoggingService log) { _log = log ?? throw new ArgumentNullException(nameof(log), $"{nameof(log)} {Resources.IsRequired}"); diff --git a/src/Maple.Core/ViewModels/Interfaces/IMediaItemsViewModel.cs b/src/Maple.Core/ViewModels/Interfaces/IMediaItemsViewModel.cs index 1c1c91b..8ab3abf 100644 --- a/src/Maple.Core/ViewModels/Interfaces/IMediaItemsViewModel.cs +++ b/src/Maple.Core/ViewModels/Interfaces/IMediaItemsViewModel.cs @@ -4,7 +4,7 @@ namespace Maple.Core { public interface IMediaItemsViewModel : ILoadableViewModel, ISaveableViewModel { - IReadOnlyCollection Items { get; } + IReadOnlyList Items { get; } void Add(Playlist playlist); } diff --git a/src/Maple.Core/ViewModels/Interfaces/IMediaPlayersViewModel.cs b/src/Maple.Core/ViewModels/Interfaces/IMediaPlayersViewModel.cs index 201e677..e3cc46b 100644 --- a/src/Maple.Core/ViewModels/Interfaces/IMediaPlayersViewModel.cs +++ b/src/Maple.Core/ViewModels/Interfaces/IMediaPlayersViewModel.cs @@ -5,6 +5,6 @@ namespace Maple.Core { public interface IMediaPlayersViewModel : ILoadableViewModel, ISaveableViewModel, IDisposable { - IReadOnlyCollection Items { get; } + IReadOnlyList Items { get; } } } \ No newline at end of file diff --git a/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs b/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs index 485aaa8..f019241 100644 --- a/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs +++ b/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading.Tasks; using Maple.Domain; -using Maple.Localization.Properties; namespace Maple.Core { @@ -11,41 +10,66 @@ public class MediaItems : ValidableBaseDataListViewModel _repositoryFactory; private readonly IMediaItemMapper _mediaItemMapper; - public MediaItems(ViewModelServiceContainer container, IMediaItemMapper mediaItemMapper, Func repositoryFactory) - : base(container) + protected MediaItems(ViewModelServiceContainer container, IMapleRepository repository) + : base(container, repository) { - _repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory), $"{nameof(repositoryFactory)} {Resources.IsRequired}"); - _mediaItemMapper = mediaItemMapper ?? throw new ArgumentNullException(nameof(mediaItemMapper), $"{nameof(mediaItemMapper)} {Resources.IsRequired}"); } + public override bool IsLoaded + { + get { throw new NotImplementedException(); } + protected set => throw new NotImplementedException(); + } + + public override IAsyncCommand SaveCommand => throw new NotImplementedException(); + + public override IAsyncCommand LoadCommand => throw new NotImplementedException(); + + public override IAsyncCommand RefreshCommand => throw new NotImplementedException(); + public void Add(Playlist playlist) { var sequence = _sequenceProvider.Get(Items.Select(p => (ISequence)p).ToList()); Add(_mediaItemMapper.GetNewMediaItem(sequence, playlist)); } - public override async Task GetCountAsync() + public override Task GetCountAsync() { - _log.Info($"{_translationService.Translate(nameof(Resources.Loading))} {_translationService.Translate(nameof(Resources.MediaItems))}"); - Clear(); - - using (var context = _repositoryFactory()) - { - var result = await context.GetMediaItemsAsync().ConfigureAwait(true); - AddRange(result); - } + throw new NotImplementedException(); + } - SelectedItem = Items.FirstOrDefault(); - IsLoaded = true; + public override Task GetItemsWithKey(int[] keys) + { + throw new NotImplementedException(); } - public override async Task SaveAsync() + public override Task SaveAsync() { - _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.MediaItems))}"); - using (var context = _repositoryFactory()) - { - await context.SaveAsync(this).ConfigureAwait(true); - } + throw new NotImplementedException(); } + + //public override async Task GetCountAsync() + //{ + // _log.Info($"{_translationService.Translate(nameof(Resources.Loading))} {_translationService.Translate(nameof(Resources.MediaItems))}"); + // Clear(); + + // using (var context = _repositoryFactory()) + // { + // var result = await context.GetMediaItemsAsync().ConfigureAwait(true); + // AddRange(result); + // } + + // SelectedItem = Items.FirstOrDefault(); + // IsLoaded = true; + //} + + //public override async Task SaveAsync() + //{ + // _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.MediaItems))}"); + // using (var context = _repositoryFactory()) + // { + // await context.SaveAsync(this).ConfigureAwait(true); + // } + //} } } diff --git a/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs index 194b263..0424034 100644 --- a/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs +++ b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs @@ -2,11 +2,10 @@ using System.Linq; using System.Threading.Tasks; using Maple.Domain; -using Maple.Localization.Properties; namespace Maple.Core { - public class MediaPlayers : VirtualizationListViewModel, IMediaPlayersViewModel + public class MediaPlayers : ValidableBaseDataListViewModel, IMediaPlayersViewModel { private readonly Func _playerFactory; private readonly AudioDevices _devices; @@ -15,37 +14,44 @@ public class MediaPlayers : VirtualizationListViewModel - /// Initializes a new instance of the class. - /// - /// The manager. - /// The player factory. - /// The repo. - /// The devices. - /// The dialog. - public MediaPlayers(ViewModelServiceContainer container, - IMediaPlayerMapper mediaPlayerMapper, - Func playerFactory, - Func repositoryFactory, - AudioDevices devices, - IDialogViewModel dialog) - : base(container) + protected MediaPlayers(ViewModelServiceContainer container, IMapleRepository repository) + : base(container, repository) { - _playerFactory = playerFactory ?? throw new ArgumentNullException(nameof(playerFactory), $"{nameof(playerFactory)} {Resources.IsRequired}"); - _devices = devices ?? throw new ArgumentNullException(nameof(devices), $"{nameof(devices)} {Resources.IsRequired}"); - _dialog = dialog ?? throw new ArgumentNullException(nameof(dialog), $"{nameof(dialog)} {Resources.IsRequired}"); - _repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory), $"{nameof(repositoryFactory)} {Resources.IsRequired}"); - _mediaPlayerMapper = mediaPlayerMapper ?? throw new ArgumentNullException(nameof(mediaPlayerMapper), $"{nameof(mediaPlayerMapper)} {Resources.IsRequired}"); + } - _notificationService = container.NotificationService; + public override bool IsLoaded + { + get { throw new NotImplementedException(); } + protected set => throw new NotImplementedException(); } + public override IAsyncCommand SaveCommand => throw new NotImplementedException(); + + public override IAsyncCommand LoadCommand => throw new NotImplementedException(); + + public override IAsyncCommand RefreshCommand => throw new NotImplementedException(); + public void Add() { var sequence = _sequenceProvider.Get(Items.Select(p => (ISequence)p).ToList()); Add(_mediaPlayerMapper.GetNewMediaPlayer(sequence)); } + public override Task GetCountAsync() + { + throw new NotImplementedException(); + } + + public override Task GetItemsWithKey(int[] keys) + { + throw new NotImplementedException(); + } + + public override Task SaveAsync() + { + throw new NotImplementedException(); + } + /// /// Releases unmanaged and - optionally - managed resources. /// @@ -67,32 +73,32 @@ protected override void Dispose(bool disposing) Disposed = true; } - public override async Task SaveAsync() - { - _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.MediaPlayers))}"); - using (var context = _repositoryFactory()) - { - await context.SaveAsync(this).ConfigureAwait(true); - } - } + //public override async Task SaveAsync() + //{ + // _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.MediaPlayers))}"); + // using (var context = _repositoryFactory()) + // { + // await context.SaveAsync(this).ConfigureAwait(true); + // } + //} - public override async Task GetCountAsync() - { - _notificationService.Info($"{_translationService.Translate(nameof(Resources.Loading))} {_translationService.Translate(nameof(Resources.MediaPlayers))}"); - Clear(); + //public override async Task GetCountAsync() + //{ + // _notificationService.Info($"{_translationService.Translate(nameof(Resources.Loading))} {_translationService.Translate(nameof(Resources.MediaPlayers))}"); + // Clear(); - using (var context = _repositoryFactory()) - { - var main = await context.GetMainMediaPlayerAsync().ConfigureAwait(true); + // using (var context = _repositoryFactory()) + // { + // var main = await context.GetMainMediaPlayerAsync().ConfigureAwait(true); - Add(main); - SelectedItem = main; + // Add(main); + // SelectedItem = main; - var others = await context.GetAllOptionalMediaPlayersAsync().ConfigureAwait(true); - AddRange(others); - } + // var others = await context.GetAllOptionalMediaPlayersAsync().ConfigureAwait(true); + // AddRange(others); + // } - IsLoaded = true; - } + // IsLoaded = true; + //} } } diff --git a/src/Maple.Core/ViewModels/Playlists/Playlists.cs b/src/Maple.Core/ViewModels/Playlists/Playlists.cs index c6e26c1..11e7291 100644 --- a/src/Maple.Core/ViewModels/Playlists/Playlists.cs +++ b/src/Maple.Core/ViewModels/Playlists/Playlists.cs @@ -1,28 +1,40 @@ using System; -using System.Linq; using System.Threading.Tasks; using Maple.Domain; -using Maple.Localization.Properties; namespace Maple.Core { public class Playlists : ValidableBaseDataListViewModel, ISaveableViewModel, IPlaylistsViewModel { - private readonly Func _repositoryFactory; - private readonly IPlaylistMapper _playlistMapper; - - public Playlists(ViewModelServiceContainer container, IPlaylistMapper playlistMapper, Func repositoryFactory) - : base(container) + public override bool IsLoaded { - _repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory), $"{nameof(repositoryFactory)} {Resources.IsRequired}"); - _playlistMapper = playlistMapper ?? throw new ArgumentNullException(nameof(playlistMapper), $"{nameof(playlistMapper)} {Resources.IsRequired}"); + get { throw new NotImplementedException(); } + protected set { throw new NotImplementedException(); } + } + + public override IAsyncCommand SaveCommand => throw new NotImplementedException(); + + public override IAsyncCommand LoadCommand => throw new NotImplementedException(); - AddCommand = new RelayCommand(Add, CanAdd); + public override IAsyncCommand RefreshCommand => throw new NotImplementedException(); + + protected Playlists(ViewModelServiceContainer container, IMapleRepository repository) + : base(container, repository) + { } + //public Playlists(ViewModelServiceContainer container, IPlaylistMapper playlistMapper, Func repositoryFactory) + // : base(container) + //{ + // _repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory), $"{nameof(repositoryFactory)} {Resources.IsRequired}"); + // _playlistMapper = playlistMapper ?? throw new ArgumentNullException(nameof(playlistMapper), $"{nameof(playlistMapper)} {Resources.IsRequired}"); + + // AddCommand = new RelayCommand(Add, CanAdd); + //} + public void Add() { - Add(_playlistMapper.GetNewPlaylist()); + //Add(_playlistMapper.GetNewPlaylist()); } public bool CanAdd() @@ -30,28 +42,43 @@ public bool CanAdd() return Items != null; } - public override async Task SaveAsync() + public override Task GetCountAsync() { - _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.Playlists))}"); - using (var context = _repositoryFactory()) - { - await context.SaveAsync(this).ConfigureAwait(true); - } + throw new NotImplementedException(); } - public override async Task GetCountAsync() + public override Task GetItemsWithKey(int[] keys) { - _log.Info($"{_translationService.Translate(nameof(Resources.Loading))} {_translationService.Translate(nameof(Resources.Playlists))}"); - Clear(); - - using (var context = _repositoryFactory()) - { - var result = await context.GetPlaylistsAsync().ConfigureAwait(true); - AddRange(result); - } + throw new NotImplementedException(); + } - SelectedItem = Items.FirstOrDefault(); - IsLoaded = true; + public override Task SaveAsync() + { + throw new NotImplementedException(); } + + //public override async Task SaveAsync() + //{ + // _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.Playlists))}"); + // using (var context = _repositoryFactory()) + // { + // await context.SaveAsync(this).ConfigureAwait(true); + // } + //} + + //public override async Task GetCountAsync() + //{ + // _log.Info($"{_translationService.Translate(nameof(Resources.Loading))} {_translationService.Translate(nameof(Resources.Playlists))}"); + // Clear(); + + // using (var context = _repositoryFactory()) + // { + // var result = await context.GetPlaylistsAsync().ConfigureAwait(true); + // AddRange(result); + // } + + // SelectedItem = Items.FirstOrDefault(); + // IsLoaded = true; + //} } } From de4c9d12ead0a38bb9c0ef642f7053c37fb82325 Mon Sep 17 00:00:00 2001 From: Peter Vietense Date: Fri, 4 May 2018 22:19:32 +0200 Subject: [PATCH 13/16] wip, added unit of work, redid generic repository, lots of refactoring --- .../Messages/Base/MapleMessageBase.cs | 3 +- src/Maple.Core/Extensions/LinqExtensions.cs | 47 +--- src/Maple.Core/IO/Base/MapleFileSystemBase.cs | 5 +- src/Maple.Core/IO/FileSystemViewModel.cs | 9 +- src/Maple.Core/Maple.Core.csproj | 7 - .../Observables/Base/ILoadableViewModel.cs | 16 +- .../Observables/Base/ISaveableViewModel.cs | 11 - src/Maple.Core/Observables/BusyStack.cs | 21 +- src/Maple.Core/Observables/BusyToken.cs | 5 +- .../ViewModels/BaseDataListViewModel.cs | 28 +-- .../ViewModels/BaseDataViewModel.cs | 3 +- .../ViewModels/BaseListViewModel.cs | 89 ++------ .../ValidableBaseDataListViewModel.cs | 80 ++++++- .../ViewModels/ValidableBaseDataViewModel.cs | 4 +- .../Virtualization/VirtualizationViewModel.cs | 14 +- .../VirtualizingCollectionViewSource.cs | 3 +- .../DataAccess/Base/BaseDataProvider.cs | 14 +- .../DataAccess/Base/IMediaRepository.cs | 28 --- .../DataAccess/MediaItemDataProvider.cs | 10 - .../DataAccess/MediaPlayerDataProvider.cs | 10 - .../Services/DataAccess/MediaRepository.cs | 207 ------------------ .../DataAccess/PlaylistDataProvider.cs | 10 - .../Services/Localization/LocalizationDTO.cs | 2 + .../Services/Mapping/Base/IBaseMapper.cs | 6 +- src/Maple.Core/Services/SquirrelLogger.cs | 5 + .../Services/Validation/Base/BaseValidator.cs | 3 + .../Services/Validation/MediaItemValidator.cs | 2 + .../Validation/MediaPlayerValidator.cs | 2 + .../Services/Validation/PlaylistValidator.cs | 2 + .../Services/Validation/PlaylistsValidator.cs | 7 +- .../IO/FileBrowserContentDialogViewModel.cs | 3 +- .../IO/FolderBrowserContentDialogViewModel.cs | 3 +- .../ViewModels/Dialogs/DialogViewModel.cs | 2 + .../Interfaces/ICultureViewModel.cs | 2 +- .../Interfaces/IMediaItemsViewModel.cs | 9 +- .../Interfaces/IMediaPlayersViewModel.cs | 8 +- .../Interfaces/IPlaylistsViewModel.cs | 3 +- .../Interfaces/IUIColorsViewModel.cs | 2 +- .../ViewModels/MediaItems/MediaItems.cs | 71 +----- .../ViewModels/MediaPlayer/MediaPlayer.cs | 7 +- .../ViewModels/MediaPlayer/MediaPlayers.cs | 98 +-------- .../ViewModels/Playlists/Playlist.cs | 7 +- .../ViewModels/Playlists/Playlists.cs | 80 +------ .../ViewModels/ViewModelServiceContainer.cs | 5 +- .../DB/CreateSeedDatabaseIfNotExists.cs | 16 +- .../{PlaylistContext.cs => MapleContext.cs} | 7 +- src/Maple.Data/Maple.Data.csproj | 13 +- .../Base/EntityFrameworkReadOnlyRepository.cs | 167 ++++++++++++++ .../Base/EntityFrameworkRepository.cs | 65 ++++++ .../Repository/Base/IMediaItemRepository.cs | 10 - .../Repository/Base/IMediaPlayerRepository.cs | 12 - .../Repository/Base/IPlaylistRepository.cs | 8 - .../Base/MaplePlaylistRepository.cs | 102 --------- src/Maple.Data/Repository/Base/UnitOfWork.cs | 79 +++++++ src/Maple.Data/Repository/MapleRepository.cs | 10 + .../Repository/MediaItemRepository.cs | 25 --- .../Repository/MediaPlayerRepository.cs | 49 ----- .../Repository/PlaylistRepository.cs | 20 -- src/Maple.Domain/Enums/RepeatMode.cs | 3 +- .../DataAccessLayer/IChangeState.cs | 11 + .../Interfaces/DataAccessLayer/IEntity.cs | 19 ++ .../DataAccessLayer/IReadOnlyRepository.cs | 84 +++++++ .../Interfaces/DataAccessLayer/IRepository.cs | 17 ++ .../{ => DataAccessLayer}/ISequence.cs | 0 .../Interfaces/DataAccessLayer/IUnitOfWork.cs | 14 ++ src/Maple.Domain/Interfaces/IAudioDevice.cs | 2 +- src/Maple.Domain/Interfaces/IBaseModel.cs | 17 -- src/Maple.Domain/Interfaces/IChangeState.cs | 20 -- src/Maple.Domain/Interfaces/IIdentifier.cs | 7 - .../Interfaces/ILoggingService.cs | 183 ---------------- .../Interfaces/IMapleRepository.cs | 17 -- src/Maple.Domain/Interfaces/IMediaItem.cs | 2 +- src/Maple.Domain/Interfaces/IMediaPlayer.cs | 39 ++-- .../Interfaces/IRangeObservableCollection.cs | 7 +- .../{ => Providers}/ITranslationProvider.cs | 0 .../Services}/ILocalizationService.cs | 2 +- .../ILoggingNotifcationService.cs | 7 +- .../Interfaces/Services/ILoggingService.cs | 139 ++++++++++++ .../{ => Services}/ISequenceService.cs | 0 .../{ => Services}/IVersionService.cs | 2 +- src/Maple.Domain/Maple.Domain.csproj | 25 ++- src/Maple.Domain/Models/Base/BaseModel.cs | 31 --- src/Maple.Domain/Models/Base/Entity.cs | 44 ++++ src/Maple.Domain/Models/MediaItemModel.cs | 4 +- src/Maple.Domain/Models/MediaPlayerModel.cs | 3 +- src/Maple.Domain/Models/PlaylistModel.cs | 4 +- src/Maple.Domain/Properties/AssemblyInfo.cs | 6 +- src/Maple/App.xaml.cs | 5 +- src/Maple/DependencyInjectionFactory.cs | 19 +- src/Maple/Shell.xaml.cs | 2 + src/Maple/SplashScreen.xaml.cs | 5 +- src/Maple/UI/Base/IIocFrameworkElement.cs | 13 +- src/Maple/UI/Base/IocUserControl.cs | 2 + src/Maple/UI/IoCResourceDictionary.cs | 2 + .../MarkupExtensions/BrushRoundConverter.cs | 3 +- .../MarkupExtensions/TranslationExtension.cs | 2 + .../UI/UserControls/MediaPlayerPage.xaml.cs | 4 +- .../UI/UserControls/MediaPlayersPage.xaml.cs | 4 +- .../Options/ColorOptionsPage.xaml.cs | 4 +- .../UserControls/Options/OptionsPage.xaml.cs | 4 +- .../Playlist/NewPlaylistOptionsPage.xaml.cs | 4 +- .../Playlist/NewPlaylistPage.xaml.cs | 4 +- .../Playlist/PlaylistsPage.xaml.cs | 4 +- src/Maple/ViewModels/Navigation/Scenes.cs | 7 +- src/Maple/ViewModels/ShellViewModel.cs | 2 + 105 files changed, 967 insertions(+), 1368 deletions(-) delete mode 100644 src/Maple.Core/Observables/Base/ISaveableViewModel.cs delete mode 100644 src/Maple.Core/Services/DataAccess/Base/IMediaRepository.cs delete mode 100644 src/Maple.Core/Services/DataAccess/MediaItemDataProvider.cs delete mode 100644 src/Maple.Core/Services/DataAccess/MediaPlayerDataProvider.cs delete mode 100644 src/Maple.Core/Services/DataAccess/MediaRepository.cs delete mode 100644 src/Maple.Core/Services/DataAccess/PlaylistDataProvider.cs rename src/Maple.Data/DB/{PlaylistContext.cs => MapleContext.cs} (86%) create mode 100644 src/Maple.Data/Repository/Base/EntityFrameworkReadOnlyRepository.cs create mode 100644 src/Maple.Data/Repository/Base/EntityFrameworkRepository.cs delete mode 100644 src/Maple.Data/Repository/Base/IMediaItemRepository.cs delete mode 100644 src/Maple.Data/Repository/Base/IMediaPlayerRepository.cs delete mode 100644 src/Maple.Data/Repository/Base/IPlaylistRepository.cs delete mode 100644 src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs create mode 100644 src/Maple.Data/Repository/Base/UnitOfWork.cs create mode 100644 src/Maple.Data/Repository/MapleRepository.cs delete mode 100644 src/Maple.Data/Repository/MediaItemRepository.cs delete mode 100644 src/Maple.Data/Repository/MediaPlayerRepository.cs delete mode 100644 src/Maple.Data/Repository/PlaylistRepository.cs create mode 100644 src/Maple.Domain/Interfaces/DataAccessLayer/IChangeState.cs create mode 100644 src/Maple.Domain/Interfaces/DataAccessLayer/IEntity.cs create mode 100644 src/Maple.Domain/Interfaces/DataAccessLayer/IReadOnlyRepository.cs create mode 100644 src/Maple.Domain/Interfaces/DataAccessLayer/IRepository.cs rename src/Maple.Domain/Interfaces/{ => DataAccessLayer}/ISequence.cs (100%) create mode 100644 src/Maple.Domain/Interfaces/DataAccessLayer/IUnitOfWork.cs delete mode 100644 src/Maple.Domain/Interfaces/IBaseModel.cs delete mode 100644 src/Maple.Domain/Interfaces/IChangeState.cs delete mode 100644 src/Maple.Domain/Interfaces/IIdentifier.cs delete mode 100644 src/Maple.Domain/Interfaces/ILoggingService.cs delete mode 100644 src/Maple.Domain/Interfaces/IMapleRepository.cs rename src/Maple.Domain/Interfaces/{ => Providers}/ITranslationProvider.cs (100%) rename src/{Maple.Core/Services/Localization => Maple.Domain/Interfaces/Services}/ILocalizationService.cs (97%) rename src/Maple.Domain/Interfaces/{ => Services}/ILoggingNotifcationService.cs (92%) create mode 100644 src/Maple.Domain/Interfaces/Services/ILoggingService.cs rename src/Maple.Domain/Interfaces/{ => Services}/ISequenceService.cs (100%) rename src/Maple.Domain/Interfaces/{ => Services}/IVersionService.cs (98%) delete mode 100644 src/Maple.Domain/Models/Base/BaseModel.cs create mode 100644 src/Maple.Domain/Models/Base/Entity.cs diff --git a/src/Maple.Core/EventAggregator/Messages/Base/MapleMessageBase.cs b/src/Maple.Core/EventAggregator/Messages/Base/MapleMessageBase.cs index b043fef..09f78ad 100644 --- a/src/Maple.Core/EventAggregator/Messages/Base/MapleMessageBase.cs +++ b/src/Maple.Core/EventAggregator/Messages/Base/MapleMessageBase.cs @@ -1,4 +1,5 @@ using System; + using Maple.Localization.Properties; namespace Maple.Core @@ -12,7 +13,7 @@ public abstract class MapleMessageBase : IMapleMessage /// Store a WeakReference to the sender just in case anyone is daft enough to /// keep the message around and prevent the sender from being collected. /// - private WeakReference _sender; + private readonly WeakReference _sender; public object Sender { get diff --git a/src/Maple.Core/Extensions/LinqExtensions.cs b/src/Maple.Core/Extensions/LinqExtensions.cs index b223f7f..d171958 100644 --- a/src/Maple.Core/Extensions/LinqExtensions.cs +++ b/src/Maple.Core/Extensions/LinqExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; + using Maple.Domain; using Maple.Localization.Properties; @@ -28,52 +29,6 @@ public static T Random(this IEnumerable baseCollection) return list.Count == 0 ? default(T) : list[r.Next(0, list.Count)]; } - /// - /// determines if some of the submitted items can be added to the collection and returns a collection of these items - /// - /// The base collection. - /// The new items. - /// - /// - /// CanAddRange can't return a result. There were no valid parameters - newItems - /// or - /// CanAddRange can't return a result. There were no valid parameters - baseCollection - /// - public static IEnumerable CanAddRange(this IList baseCollection, IList newItems) - { - if (baseCollection == null) - throw new ArgumentNullException(nameof(baseCollection), $"{nameof(baseCollection)} {Resources.IsRequired}"); - - if (newItems?.Any() != true) - throw new ArgumentNullException(nameof(newItems), $"{nameof(newItems)} {Resources.IsRequired}"); - - var excludedIDs = new HashSet(baseCollection.Select(p => p.Id)); - return newItems.Where(p => !excludedIDs.Contains(p.Id)); - } - - /// - /// determines if some of the submitted items can be added to the collection and returns a collection of these items - /// - /// The base collection. - /// The new items. - /// - /// - /// CanAddRange can't return a result. There were no valid parameters - newItems - /// or - /// CanAddRange can't return a result. There were no valid parameters - baseCollection - /// - public static IEnumerable CanAddRange(this IList baseCollection, IList newItems) - { - if (baseCollection == null) - throw new ArgumentNullException(nameof(baseCollection), $"{nameof(baseCollection)} {Resources.IsRequired}"); - - if (newItems?.Any() != true) - throw new ArgumentNullException(nameof(newItems), $"{nameof(newItems)} {Resources.IsRequired}"); - - var excludedIDs = new HashSet(baseCollection.Select(p => p.Id)); - return newItems.Where(p => !excludedIDs.Contains(p.Id)); - } - public static IEnumerable ForEach(this IEnumerable baseCollection, Func action) { if (baseCollection == null) diff --git a/src/Maple.Core/IO/Base/MapleFileSystemBase.cs b/src/Maple.Core/IO/Base/MapleFileSystemBase.cs index 712e670..b0a5d1a 100644 --- a/src/Maple.Core/IO/Base/MapleFileSystemBase.cs +++ b/src/Maple.Core/IO/Base/MapleFileSystemBase.cs @@ -1,5 +1,6 @@ using System; using System.Windows.Input; + using Maple.Localization.Properties; namespace Maple.Core @@ -16,9 +17,7 @@ public static bool NoFilesFilter(object obj) public static bool SearchFilter(object obj) { - var info = obj as IFileSystemInfo; - - if (info == null) + if (!(obj is IFileSystemInfo info)) return false; if (info.IsHidden || info.IsBusy) diff --git a/src/Maple.Core/IO/FileSystemViewModel.cs b/src/Maple.Core/IO/FileSystemViewModel.cs index eea2689..ef2a498 100644 --- a/src/Maple.Core/IO/FileSystemViewModel.cs +++ b/src/Maple.Core/IO/FileSystemViewModel.cs @@ -2,6 +2,7 @@ using System.IO; using System.Linq; using System.Windows.Input; + using Maple.Domain; namespace Maple.Core @@ -117,9 +118,7 @@ private void OnSelectedItemChanged() public void SetSelectedItem(object item) { - var value = item as MapleFileSystemContainerBase; - - if (value == null) + if (!(item is MapleFileSystemContainerBase value)) return; SelectedItem = value; @@ -132,9 +131,7 @@ private bool CanSetSelectedItem(object item) if (item == null) return false; - var value = item as MapleFileSystemContainerBase; - - return value != null && value != SelectedItem; + return item is MapleFileSystemContainerBase value && value != SelectedItem; } } } diff --git a/src/Maple.Core/Maple.Core.csproj b/src/Maple.Core/Maple.Core.csproj index 93b6a0e..ca05fef 100644 --- a/src/Maple.Core/Maple.Core.csproj +++ b/src/Maple.Core/Maple.Core.csproj @@ -111,10 +111,6 @@ - - - - @@ -147,7 +143,6 @@ Settings.settings - @@ -185,8 +180,6 @@ - - diff --git a/src/Maple.Core/Observables/Base/ILoadableViewModel.cs b/src/Maple.Core/Observables/Base/ILoadableViewModel.cs index fc150cd..86b44ee 100644 --- a/src/Maple.Core/Observables/Base/ILoadableViewModel.cs +++ b/src/Maple.Core/Observables/Base/ILoadableViewModel.cs @@ -1,21 +1,7 @@ -using System.Threading.Tasks; - -namespace Maple.Core +namespace Maple.Core { - public interface ILoadableViewModel : ILoadableViewModel - { - Task GetCountAsync(); - Task GetItemsWithKey(TKey[] keys); - } - public interface ILoadableViewModel { - /// - /// Gets a value indicating whether this instance is loaded. - /// - /// - /// true if this instance is loaded; otherwise, false. - /// bool IsLoaded { get; } IAsyncCommand LoadCommand { get; } diff --git a/src/Maple.Core/Observables/Base/ISaveableViewModel.cs b/src/Maple.Core/Observables/Base/ISaveableViewModel.cs deleted file mode 100644 index 30e21ab..0000000 --- a/src/Maple.Core/Observables/Base/ISaveableViewModel.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Threading.Tasks; - -namespace Maple.Core -{ - public interface ISaveableViewModel - { - IAsyncCommand SaveCommand { get; } - - Task SaveAsync(); - } -} diff --git a/src/Maple.Core/Observables/BusyStack.cs b/src/Maple.Core/Observables/BusyStack.cs index 02dba57..06be200 100644 --- a/src/Maple.Core/Observables/BusyStack.cs +++ b/src/Maple.Core/Observables/BusyStack.cs @@ -1,5 +1,8 @@ using System; using System.Collections.Concurrent; +using System.Threading.Tasks; +using System.Windows; + using Maple.Localization.Properties; namespace Maple.Core @@ -20,7 +23,7 @@ public class BusyStack : ObservableObject protected ConcurrentBag Items { get { return _items; } - set { SetValue(ref _items, value, InvokeOnChanged); } + set { SetValue(ref _items, value, async () => await InvokeOnChanged()); } } private Action _onChanged; @@ -60,12 +63,12 @@ public BusyStack(Action onChanged) /// Tries to take an item from the stack and returns true if that action was successful /// /// - public bool Pull() + public async Task Pull() { - var result = Items.TryTake(out BusyToken token); + var result = Items.TryTake(out var token); if (result) - InvokeOnChanged(); + await InvokeOnChanged(); return result; } @@ -74,11 +77,11 @@ public bool Pull() /// Adds a new to the Stack /// /// The token. - public void Push(BusyToken token) + public async Task Push(BusyToken token) { Items.Add(token); - InvokeOnChanged(); + await InvokeOnChanged(); } /// @@ -89,7 +92,7 @@ public void Push(BusyToken token) /// public bool HasItems() { - return Items?.TryPeek(out BusyToken token) ?? false; + return Items?.TryPeek(out var token) ?? false; } /// @@ -103,9 +106,9 @@ public BusyToken GetToken() return new BusyToken(this); } - private void InvokeOnChanged() + private async Task InvokeOnChanged() { - DispatcherFactory.Invoke(OnChanged, HasItems()); + await Application.Current.Dispatcher.InvokeAsync(() => OnChanged(HasItems())); } } } diff --git a/src/Maple.Core/Observables/BusyToken.cs b/src/Maple.Core/Observables/BusyToken.cs index f8ce9af..aad612a 100644 --- a/src/Maple.Core/Observables/BusyToken.cs +++ b/src/Maple.Core/Observables/BusyToken.cs @@ -23,9 +23,10 @@ public class BusyToken : WeakReference, IDisposable /// Initializes a new instance of the class. /// /// The stack. - public BusyToken(BusyStack stack) : base(stack) + public BusyToken(BusyStack stack) + : base(stack) { - stack.Push(this); + stack.Push(this).GetAwaiter().GetResult(); } /// diff --git a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs index 941f1ce..daba5eb 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Linq; -using System.Threading.Tasks; + using Maple.Domain; using Maple.Localization.Properties; @@ -11,25 +11,15 @@ namespace Maple.Core { // TODO add virtualization here // - public abstract class BaseDataListViewModel : BaseListViewModel, ILoadableViewModel, ISaveableViewModel + public abstract class BaseDataListViewModel : BaseListViewModel where TViewModel : VirtualizationViewModel, ISequence - where TModel : class, IBaseModel + where TModel : class, IEntity { - private readonly IMapleRepository _repository; - protected readonly ISequenceService _sequenceProvider; protected readonly ILocalizationService _translationService; protected readonly ILoggingService _log; - public abstract bool IsLoaded { get; protected set; } - - public abstract IAsyncCommand SaveCommand { get; } - public abstract IAsyncCommand LoadCommand { get; } - public abstract IAsyncCommand RefreshCommand { get; } - - public abstract Task GetCountAsync(); - public abstract Task SaveAsync(); - public abstract Task GetItemsWithKey(TKeyDataType[] keys); + protected IRepository Repository { get; } private ICollectionView _view; /// @@ -44,16 +34,16 @@ public ICollectionView View protected set { SetValue(ref _view, value); } } - protected BaseDataListViewModel(ViewModelServiceContainer container, IMapleRepository repository) + protected BaseDataListViewModel(ViewModelServiceContainer container) : base(container.Messenger) { - _repository = repository ?? throw new ArgumentNullException(nameof(repository), $"{nameof(repository)} {Resources.IsRequired}"); + Repository = container.Repository; _log = container.Log; _translationService = container.LocalizationService; _sequenceProvider = container.SequenceService; - View = new VirtualizingCollectionViewSource(container, _items); + View = new VirtualizingCollectionViewSource(container, Items); } /// @@ -69,7 +59,7 @@ public override void Remove(TViewModel container) { while (Items.Contains(container)) { - container.ViewModel.Model.IsDeleted = true; + Repository.Delete(container.ViewModel.Model); base.Remove(container); } } @@ -86,7 +76,7 @@ public override void RemoveRange(IEnumerable items) using (BusyStack.GetToken()) { - items.ForEach(p => p.ViewModel.Model.IsDeleted = true); + items.ForEach(p => Remove(p)); base.RemoveRange(items); } } diff --git a/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs index 83c49a6..c3709ec 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs @@ -1,11 +1,10 @@ using System; using System.Runtime.CompilerServices; -using Maple.Domain; namespace Maple.Core { public abstract class BaseDataViewModel : BaseViewModel - where TModel : class, IBaseModel + where TModel : class { protected ChangeTracker ChangeTracker { get; } protected bool SkipChangeTracking { get; set; } diff --git a/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs index ad1f822..d2c0341 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs @@ -1,8 +1,8 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel; -using System.Diagnostics; using System.Linq; using System.Windows.Input; @@ -28,144 +28,81 @@ public TViewModel SelectedItem } } - protected RangeObservableCollection _items; - /// - /// Contains all the UI relevant Models and notifies about changes in the collection and inside the Models themself - /// - [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] - public IReadOnlyList Items - { - get { return _items; } - protected set { SetValue(ref _items, (RangeObservableCollection)value); } - } + protected ObservableCollection Items { get; } + public ReadOnlyCollection ReadOnlyItems { get; } - /// - /// Gets the at the specified index. - /// - /// - /// The . - /// - /// The index. - /// public TViewModel this[int index] { - get { return _items[index]; } + get { return Items[index]; } } public ICommand RemoveRangeCommand { get; private set; } public ICommand RemoveCommand { get; private set; } public ICommand ClearCommand { get; private set; } - public ICommand AddCommand { get; protected set; } protected BaseListViewModel(IMessenger messenger) : base(messenger) { - _items = new RangeObservableCollection(); + Items = new ObservableCollection(); + ReadOnlyItems = new ReadOnlyCollection(Items); RemoveCommand = new RelayCommand(Remove, CanRemove); RemoveRangeCommand = new RelayCommand(RemoveRange, CanRemoveRange); - ClearCommand = new RelayCommand(() => Clear(), CanClear); - } - - protected BaseListViewModel(IEnumerable items, IMessenger messenger) - : this(messenger) - { - AddRange(items); + ClearCommand = new RelayCommand(Clear, CanClear); } - /// - /// Adds the specified item. - /// - /// The item. - /// item public virtual void Add(TViewModel item) { if (item == null) throw new ArgumentNullException(nameof(item)); using (BusyStack.GetToken()) - _items.Add(item); + Items.Add(item); } - /// The items. - /// items public virtual void AddRange(IEnumerable items) { if (items == null) throw new ArgumentNullException(nameof(items)); using (BusyStack.GetToken()) - _items.AddRange(items); - } - - protected virtual bool CanAdd(TViewModel item) - { - return Items != null && item != null; + Items.ForEach(p => Add(p)); } - /// - /// Removes the specified item. - /// - /// The item. public virtual void Remove(TViewModel item) { using (BusyStack.GetToken()) - _items.Remove(item); + Items.Remove(item); } - /// The items. - /// items public virtual void RemoveRange(IEnumerable items) { if (items == null) throw new ArgumentNullException(nameof(items)); using (BusyStack.GetToken()) - _items.RemoveRange(items); + Items.ForEach(p => Remove(p)); } - /// The items. - /// items public virtual void RemoveRange(IList items) { if (items == null) throw new ArgumentNullException(nameof(items)); using (BusyStack.GetToken()) - _items.RemoveRange(items.Cast()); + Items.ForEach(p => Remove(p)); } - /// - /// Determines whether this instance can remove the specified item. - /// - /// The item. - /// - /// true if this instance can remove the specified item; otherwise, false. - /// public virtual bool CanRemove(TViewModel item) { return CanClear() && item != null && Items.Contains(item); } - /// - /// Checks if any of the submitted items can be removed - /// - /// The items. - /// - /// true if this instance [can remove range] the specified items; otherwise, false. - /// public virtual bool CanRemoveRange(IEnumerable items) { return CanClear() && items != null && items.Any(p => Items.Contains(p)); } - /// - /// Determines whether this instance [can remove range] the specified items. - /// - /// The items. - /// - /// true if this instance [can remove range] the specified items; otherwise, false. - /// public virtual bool CanRemoveRange(IList items) { return items == null ? false : CanRemoveRange(items.Cast()); @@ -176,7 +113,7 @@ public virtual void Clear() SelectedItem = default(TViewModel); using (BusyStack.GetToken()) - _items.Clear(); + Items.Clear(); } public virtual bool CanClear() diff --git a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs index adc56ce..8ae71e0 100644 --- a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs @@ -1,16 +1,84 @@ -using Maple.Domain; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Input; + +using Maple.Domain; namespace Maple.Core { - public abstract class ValidableBaseDataListViewModel : BaseDataListViewModel + // TODO add logic for handling INotifyDataErrorInfo for children and on this + public abstract class ValidableBaseDataListViewModel : BaseDataListViewModel, ILoadableViewModel, IVirtualizedListViewModel where TViewModel : VirtualizationViewModel, ISequence - where TModel : class, IBaseModel + where TModel : class, IEntity, new() { - protected ValidableBaseDataListViewModel(ViewModelServiceContainer container, IMapleRepository repository) - : base(container, repository) + public bool IsLoaded { get; protected set; } + + public IAsyncCommand LoadCommand { get; } + public IAsyncCommand RefreshCommand { get; } + + public ICommand AddCommand { get; } + + protected ValidableBaseDataListViewModel(ViewModelServiceContainer container) + : base(container) { + AddCommand = new RelayCommand(Add, CanAdd); + LoadCommand = AsyncCommand.Create(Load, CanLoad); + RefreshCommand = AsyncCommand.Create(Refresh, CanRefresh); } - // TODO add logic for handling INotifyDataErrorInfo for children and on this + private void Add() + { + // create new instance + // add to repo + // wrap in viewmodel + // add to internal list + } + + private bool CanAdd() + { + return Items != null; + } + + private Task Load(CancellationToken token) + { + throw new NotImplementedException(); + } + + private bool CanLoad() + { + return !IsLoaded && !IsBusy; + } + + private Task Refresh() + { + throw new NotImplementedException(); + } + + private bool CanRefresh() + { + return !IsBusy; + } + + protected Task GetCountAsync() + { + return Repository.GetCountAsync(); + } + + protected async Task> GetItemsWithKey(ICollection ids) + { + return await Repository.GetByIdsAsync(ids); + } + + public void ExtendItems(IEnumerable items) + { + throw new System.NotImplementedException(); + } + + public void DeflateItem(object item) + { + throw new System.NotImplementedException(); + } } } diff --git a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs index 000abb4..bbdf31e 100644 --- a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs @@ -5,8 +5,10 @@ using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; + using FluentValidation; using FluentValidation.Results; + using Maple.Domain; using Maple.Localization.Properties; @@ -14,7 +16,7 @@ namespace Maple.Core { public abstract class ValidableBaseDataViewModel : BaseDataViewModel, INotifyDataErrorInfo where TViewModel : BaseDataViewModel, ISequence - where TModel : class, IBaseModel + where TModel : class, IEntity { protected bool SkipValidation { get; set; } diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs index 397888f..68f537a 100644 --- a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs +++ b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs @@ -1,22 +1,18 @@ using System; using System.Threading.Tasks; using System.Windows.Input; -using Maple.Domain; + using Maple.Localization.Properties; namespace Maple.Core { + // container for one viewmodel public class VirtualizationViewModel : ObservableObject - where TModel : class, IBaseModel + where TModel : class { private readonly IDataProvider, TKeyDataType> _dataProvider; - private TKeyDataType _id; - public TKeyDataType Id - { - get { return _id; } - private set { SetValue(ref _id, value); } - } + private readonly TKeyDataType _id; private bool _isExtended; public bool IsExtended @@ -74,7 +70,7 @@ public async Task Expand() if (ViewModel != null) return; - ViewModel = await _dataProvider.Get(Id).ConfigureAwait(true); + ViewModel = await _dataProvider.Get(_id).ConfigureAwait(true); IsExtended = true; } diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizingCollectionViewSource.cs b/src/Maple.Core/Observables/Virtualization/VirtualizingCollectionViewSource.cs index 13ca4b4..d0fe8fc 100644 --- a/src/Maple.Core/Observables/Virtualization/VirtualizingCollectionViewSource.cs +++ b/src/Maple.Core/Observables/Virtualization/VirtualizingCollectionViewSource.cs @@ -4,11 +4,12 @@ using System.Runtime.Caching; using System.Windows.Data; using System.Windows.Threading; + using Maple.Localization.Properties; namespace Maple.Core { - public class VirtualizingCollectionViewSource : ListCollectionView + public sealed class VirtualizingCollectionViewSource : ListCollectionView { private readonly IVirtualizedListViewModel _sponsor; private readonly HashSet _deferredItems; diff --git a/src/Maple.Core/Services/DataAccess/Base/BaseDataProvider.cs b/src/Maple.Core/Services/DataAccess/Base/BaseDataProvider.cs index e837912..18b3854 100644 --- a/src/Maple.Core/Services/DataAccess/Base/BaseDataProvider.cs +++ b/src/Maple.Core/Services/DataAccess/Base/BaseDataProvider.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; + +using Maple.Domain; using Maple.Localization.Properties; namespace Maple.Core @@ -9,12 +11,10 @@ public abstract class BaseDataProvider : IDataProvi where TViewModel : class { private readonly ICachingService _cache; - private readonly Func> _viewModelFactory; - protected BaseDataProvider(Func> viewModelFactory, ICachingService cache) + protected BaseDataProvider(IRepository mapleRepository, ICachingService cache) { _cache = cache ?? throw new ArgumentNullException(nameof(cache), $"{nameof(cache)} {Resources.IsRequired}"); - _viewModelFactory = viewModelFactory ?? throw new ArgumentNullException(nameof(viewModelFactory), $"{nameof(viewModelFactory)} {Resources.IsRequired}"); } public async Task Chunk(IEnumerable Ids) @@ -36,9 +36,15 @@ public async Task Get(TPrimaryKeyType key) return await InternalGet(key).ConfigureAwait(false); } + private async Task InternalGet(TPrimaryKeyType key) { - return await _viewModelFactory(key).ConfigureAwait(false); + throw new NotImplementedException(); + + // check cache for entry + // ask repository for entry + // wrap result with mapper + // return result } public void Clear() diff --git a/src/Maple.Core/Services/DataAccess/Base/IMediaRepository.cs b/src/Maple.Core/Services/DataAccess/Base/IMediaRepository.cs deleted file mode 100644 index a2769d8..0000000 --- a/src/Maple.Core/Services/DataAccess/Base/IMediaRepository.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Maple.Core -{ - public interface IMediaRepository : IDisposable - { - bool IsBusy { get; } - - Task SaveAsync(MediaItem viewModel); - Task SaveAsync(MediaItems viewModel); - Task GetMediaItemByIdAsync(int id); - Task> GetMediaItemsAsync(); - Task GetMediaItemByPlaylistIdAsync(int id); - - Task SaveAsync(Playlist viewModel); - Task SaveAsync(Playlists viewModel); - Task GetPlaylistByIdAsync(int id); - Task> GetPlaylistsAsync(); - - Task SaveAsync(MediaPlayer viewModel); - Task SaveAsync(MediaPlayers viewModel); - Task GetMainMediaPlayerAsync(); - Task GetMediaPlayerByIdAsync(int id); - Task> GetAllOptionalMediaPlayersAsync(); - } -} \ No newline at end of file diff --git a/src/Maple.Core/Services/DataAccess/MediaItemDataProvider.cs b/src/Maple.Core/Services/DataAccess/MediaItemDataProvider.cs deleted file mode 100644 index d0dadaf..0000000 --- a/src/Maple.Core/Services/DataAccess/MediaItemDataProvider.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Maple.Core -{ - public class MediaItemDataProvider : BaseDataProvider - { - protected MediaItemDataProvider(IMediaRepository mediaRepository, ICachingService cache) - : base(mediaRepository.GetMediaItemByIdAsync, cache) - { - } - } -} diff --git a/src/Maple.Core/Services/DataAccess/MediaPlayerDataProvider.cs b/src/Maple.Core/Services/DataAccess/MediaPlayerDataProvider.cs deleted file mode 100644 index f9c9ec9..0000000 --- a/src/Maple.Core/Services/DataAccess/MediaPlayerDataProvider.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Maple.Core -{ - public class MediaPlayerDataProvider : BaseDataProvider - { - protected MediaPlayerDataProvider(IMediaRepository mediaRepository, ICachingService cache) - : base(mediaRepository.GetMediaPlayerByIdAsync, cache) - { - } - } -} diff --git a/src/Maple.Core/Services/DataAccess/MediaRepository.cs b/src/Maple.Core/Services/DataAccess/MediaRepository.cs deleted file mode 100644 index 8bba135..0000000 --- a/src/Maple.Core/Services/DataAccess/MediaRepository.cs +++ /dev/null @@ -1,207 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; -using Maple.Data; -using Maple.Localization.Properties; - -namespace Maple.Core -{ - // helpful: https://blog.oneunicorn.com/2012/03/10/secrets-of-detectchanges-part-1-what-does-detectchanges-do/ - /// - /// Provides a way to access all playback related data on the DAL - /// - /// - public class MediaRepository : IMediaRepository - { - private const int _saveThreshold = 100; - - private readonly IMediaItemRepository _mediaItemRepository; - private readonly IMediaPlayerRepository _mediaPlayerRepository; - private readonly IPlaylistRepository _playlistRepository; - - private readonly IPlaylistMapper _playlistMapper; - private readonly IMediaPlayerMapper _mediaPlayerMapper; - private readonly IMediaItemMapper _mediaItemMapper; - - private readonly BusyStack _busyStack; - - private bool _disposed = false; - - public bool IsBusy { get; private set; } - - public MediaRepository(IPlaylistMapper playlistMapper, - IMediaItemMapper mediaItemMapper, - IMediaPlayerMapper mediaPlayerMapper, - IMediaItemRepository mediaItemRepository, - IMediaPlayerRepository mediaPlayerRepository, - IPlaylistRepository playlistRepository) - { - _mediaItemMapper = mediaItemMapper ?? throw new ArgumentNullException(nameof(mediaItemMapper), $"{nameof(mediaItemMapper)} {Resources.IsRequired}"); - _playlistMapper = playlistMapper ?? throw new ArgumentNullException(nameof(playlistMapper), $"{nameof(playlistMapper)} {Resources.IsRequired}"); - _mediaPlayerMapper = mediaPlayerMapper ?? throw new ArgumentNullException(nameof(mediaPlayerMapper), $"{nameof(mediaPlayerMapper)} {Resources.IsRequired}"); - - _mediaItemRepository = mediaItemRepository ?? throw new ArgumentNullException(nameof(mediaItemRepository), $"{nameof(mediaItemRepository)} {Resources.IsRequired}"); - _mediaPlayerRepository = mediaPlayerRepository ?? throw new ArgumentNullException(nameof(mediaPlayerRepository), $"{nameof(mediaPlayerRepository)} {Resources.IsRequired}"); - _playlistRepository = playlistRepository ?? throw new ArgumentNullException(nameof(playlistRepository), $"{nameof(playlistRepository)} {Resources.IsRequired}"); - - _busyStack = new BusyStack(); - _busyStack.OnChanged += (hasItems) => { IsBusy = hasItems; }; - } - - public async Task SaveAsync(MediaItem viewModel) - { - using (_busyStack.GetToken()) - await _mediaItemRepository.SaveAsync(viewModel.Model).ConfigureAwait(false); - } - - public async Task SaveAsync(MediaItems viewModel) - { - using (_busyStack.GetToken()) - { - var tasks = new List(viewModel.Items.Select(p => SaveAsync(p))); - await Task.WhenAll(tasks).ConfigureAwait(true); - } - } - - public async Task GetMediaItemByIdAsync(int id) - { - using (_busyStack.GetToken()) - { - var item = await _mediaItemRepository.GetByIdAsync(id) - .ConfigureAwait(false); - return _mediaItemMapper.Get(item); - } - } - - public async Task> GetMediaItemsAsync() - { - using (_busyStack.GetToken()) - { - var items = await _mediaItemRepository.GetAsync() - .ConfigureAwait(false); - return items.Select(p => _mediaItemMapper.Get(p)) - .ToList(); - } - } - - public async Task GetMediaItemByPlaylistIdAsync(int id) - { - using (_busyStack.GetToken()) - { - var item = await _mediaItemRepository.GetMediaItemByPlaylistIdAsync(id) - .ConfigureAwait(false); - return _mediaItemMapper.Get(item); - } - } - - public async Task SaveAsync(Playlist viewModel) - { - if (!viewModel.IsChanged) - return; - - using (_busyStack.GetToken()) - await _playlistRepository.SaveAsync(viewModel.Model).ConfigureAwait(false); - } - - public async Task SaveAsync(Playlists viewModel) - { - using (_busyStack.GetToken()) - { - var tasks = new List(viewModel.Items.Select(p => SaveAsync(p))); - await Task.WhenAll(tasks).ConfigureAwait(false); ; - } - } - - public async Task GetPlaylistByIdAsync(int id) - { - using (_busyStack.GetToken()) - { - var item = await _playlistRepository.GetByIdAsync(id) - .ConfigureAwait(false); - return _playlistMapper.Get(item); - } - } - - public async Task> GetPlaylistsAsync() - { - using (_busyStack.GetToken()) - { - var items = await _playlistRepository.GetAsync() - .ConfigureAwait(false); - return items.Select(p => _playlistMapper.Get(p)) - .ToList(); - } - } - - public async Task SaveAsync(MediaPlayer viewModel) - { - using (_busyStack.GetToken()) - await _mediaPlayerRepository.SaveAsync(viewModel.Model).ConfigureAwait(false); - } - - public async Task SaveAsync(MediaPlayers viewModel) - { - using (_busyStack.GetToken()) - { - var tasks = new List(viewModel.Items.Select(p => SaveAsync(p))); - await Task.WhenAll(tasks).ConfigureAwait(true); - } - } - - public async Task GetMainMediaPlayerAsync() - { - using (_busyStack.GetToken()) - { - var item = await _mediaPlayerRepository.GetMainMediaPlayerAsync() - .ConfigureAwait(false); - return _mediaPlayerMapper.GetMain(item, _playlistMapper.Get(item.Playlist)); - } - } - - public async Task GetMediaPlayerByIdAsync(int id) - { - using (_busyStack.GetToken()) - { - var item = await _mediaPlayerRepository.GetByIdAsync(id) - .ConfigureAwait(false); - return _mediaPlayerMapper.Get(item); - } - } - - public async Task> GetAllOptionalMediaPlayersAsync() - { - using (_busyStack.GetToken()) - { - var items = await _mediaPlayerRepository.GetOptionalMediaPlayersAsync() - .ConfigureAwait(false); - return items.Select(p => _mediaPlayerMapper.Get(p)) - .ToList(); - } - } - - [DebuggerStepThrough] - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - // Protected implementation of Dispose pattern. - protected virtual void Dispose(bool disposing) - { - if (_disposed) - return; - - if (disposing) - { - - // Free any other managed objects here. - } - - // Free any unmanaged objects here. - _disposed = true; - } - } -} diff --git a/src/Maple.Core/Services/DataAccess/PlaylistDataProvider.cs b/src/Maple.Core/Services/DataAccess/PlaylistDataProvider.cs deleted file mode 100644 index 86b3cc9..0000000 --- a/src/Maple.Core/Services/DataAccess/PlaylistDataProvider.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Maple.Core -{ - public class PlaylistDataProvider : BaseDataProvider - { - protected PlaylistDataProvider(IMediaRepository mediaRepository, ICachingService cache) - : base(mediaRepository.GetPlaylistByIdAsync, cache) - { - } - } -} diff --git a/src/Maple.Core/Services/Localization/LocalizationDTO.cs b/src/Maple.Core/Services/Localization/LocalizationDTO.cs index 6e762f7..c77666b 100644 --- a/src/Maple.Core/Services/Localization/LocalizationDTO.cs +++ b/src/Maple.Core/Services/Localization/LocalizationDTO.cs @@ -1,6 +1,8 @@ using System; using System.ComponentModel; using System.Windows; + +using Maple.Domain; using Maple.Localization.Properties; namespace Maple.Core diff --git a/src/Maple.Core/Services/Mapping/Base/IBaseMapper.cs b/src/Maple.Core/Services/Mapping/Base/IBaseMapper.cs index 8352d95..793a1f2 100644 --- a/src/Maple.Core/Services/Mapping/Base/IBaseMapper.cs +++ b/src/Maple.Core/Services/Mapping/Base/IBaseMapper.cs @@ -1,10 +1,8 @@ -using Maple.Domain; - -namespace Maple.Core +namespace Maple.Core { public interface IBaseMapper where TVieModel : BaseDataViewModel - where TDataModel : class, IBaseModel + where TDataModel : class { TVieModel Get(TDataModel model); diff --git a/src/Maple.Core/Services/SquirrelLogger.cs b/src/Maple.Core/Services/SquirrelLogger.cs index 952143c..230c5ed 100644 --- a/src/Maple.Core/Services/SquirrelLogger.cs +++ b/src/Maple.Core/Services/SquirrelLogger.cs @@ -1,8 +1,11 @@ using System; using System.ComponentModel; + using Maple.Domain; using Maple.Localization.Properties; +using Splat; + namespace Maple { /// @@ -17,6 +20,8 @@ public SquirrelLogger(ILoggingService log) _log = log ?? throw new ArgumentNullException(nameof(log), $"{nameof(log)} {Resources.IsRequired}"); } + public LogLevel Level { get; set; } + public void Error(object message) { _log.Error(message); diff --git a/src/Maple.Core/Services/Validation/Base/BaseValidator.cs b/src/Maple.Core/Services/Validation/Base/BaseValidator.cs index 2329137..492664f 100644 --- a/src/Maple.Core/Services/Validation/Base/BaseValidator.cs +++ b/src/Maple.Core/Services/Validation/Base/BaseValidator.cs @@ -1,5 +1,8 @@ using System; + using FluentValidation; + +using Maple.Domain; using Maple.Localization.Properties; namespace Maple.Core diff --git a/src/Maple.Core/Services/Validation/MediaItemValidator.cs b/src/Maple.Core/Services/Validation/MediaItemValidator.cs index e726471..23b9856 100644 --- a/src/Maple.Core/Services/Validation/MediaItemValidator.cs +++ b/src/Maple.Core/Services/Validation/MediaItemValidator.cs @@ -1,5 +1,7 @@ using FluentValidation; +using Maple.Domain; + namespace Maple.Core { public class MediaItemValidator : BaseValidator, IValidator diff --git a/src/Maple.Core/Services/Validation/MediaPlayerValidator.cs b/src/Maple.Core/Services/Validation/MediaPlayerValidator.cs index 1763dd0..c872e14 100644 --- a/src/Maple.Core/Services/Validation/MediaPlayerValidator.cs +++ b/src/Maple.Core/Services/Validation/MediaPlayerValidator.cs @@ -1,5 +1,7 @@ using FluentValidation; +using Maple.Domain; + namespace Maple.Core { public class MediaPlayerValidator : BaseValidator, IValidator diff --git a/src/Maple.Core/Services/Validation/PlaylistValidator.cs b/src/Maple.Core/Services/Validation/PlaylistValidator.cs index 2aee28f..cbc421d 100644 --- a/src/Maple.Core/Services/Validation/PlaylistValidator.cs +++ b/src/Maple.Core/Services/Validation/PlaylistValidator.cs @@ -1,5 +1,7 @@ using FluentValidation; +using Maple.Domain; + namespace Maple.Core { public class PlaylistValidator : BaseValidator, IValidator diff --git a/src/Maple.Core/Services/Validation/PlaylistsValidator.cs b/src/Maple.Core/Services/Validation/PlaylistsValidator.cs index 403a159..804082c 100644 --- a/src/Maple.Core/Services/Validation/PlaylistsValidator.cs +++ b/src/Maple.Core/Services/Validation/PlaylistsValidator.cs @@ -1,5 +1,7 @@ using FluentValidation; +using Maple.Domain; + namespace Maple.Core { public class PlaylistsValidator : BaseValidator, IValidator @@ -7,8 +9,9 @@ public class PlaylistsValidator : BaseValidator, IValidator playlistValidator) : base(translationService) { - RuleFor(playlists => playlists.Items).NotEmpty() - .SetCollectionValidator(playlistValidator); + RuleFor(playlists => playlists.ReadOnlyItems) + .NotEmpty() + .SetCollectionValidator(playlistValidator); } } } diff --git a/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs index 47863f5..f0862f4 100644 --- a/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs @@ -1,11 +1,12 @@ using System; + using Maple.Localization.Properties; namespace Maple.Core { public class FileBrowserContentDialogViewModel : ObservableObject { - private FileSystemBrowserOptions _options; + private readonly FileSystemBrowserOptions _options; private FileSystemViewModel _fileSystemViewModel; public FileSystemViewModel FileSystemViewModel diff --git a/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs index fd3031a..d16c9c2 100644 --- a/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs @@ -1,11 +1,12 @@ using System; + using Maple.Localization.Properties; namespace Maple.Core { public class FolderBrowserContentDialogViewModel : ObservableObject { - private FileSystemBrowserOptions _options; + private readonly FileSystemBrowserOptions _options; private FileSystemViewModel _fileSystemViewModel; public FileSystemViewModel FileSystemViewModel diff --git a/src/Maple.Core/ViewModels/Dialogs/DialogViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/DialogViewModel.cs index a3a368c..8d8ac4d 100644 --- a/src/Maple.Core/ViewModels/Dialogs/DialogViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogViewModel.cs @@ -3,6 +3,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; + +using Maple.Domain; using Maple.Localization.Properties; using Maple.Youtube; diff --git a/src/Maple.Core/ViewModels/Interfaces/ICultureViewModel.cs b/src/Maple.Core/ViewModels/Interfaces/ICultureViewModel.cs index 1322922..587971d 100644 --- a/src/Maple.Core/ViewModels/Interfaces/ICultureViewModel.cs +++ b/src/Maple.Core/ViewModels/Interfaces/ICultureViewModel.cs @@ -1,6 +1,6 @@ namespace Maple.Core { - public interface ICultureViewModel : ILoadableViewModel, ISaveableViewModel + public interface ICultureViewModel : ILoadableViewModel { } } \ No newline at end of file diff --git a/src/Maple.Core/ViewModels/Interfaces/IMediaItemsViewModel.cs b/src/Maple.Core/ViewModels/Interfaces/IMediaItemsViewModel.cs index 8ab3abf..6c19af1 100644 --- a/src/Maple.Core/ViewModels/Interfaces/IMediaItemsViewModel.cs +++ b/src/Maple.Core/ViewModels/Interfaces/IMediaItemsViewModel.cs @@ -1,11 +1,6 @@ -using System.Collections.Generic; - -namespace Maple.Core +namespace Maple.Core { - public interface IMediaItemsViewModel : ILoadableViewModel, ISaveableViewModel + public interface IMediaItemsViewModel : ILoadableViewModel { - IReadOnlyList Items { get; } - - void Add(Playlist playlist); } } \ No newline at end of file diff --git a/src/Maple.Core/ViewModels/Interfaces/IMediaPlayersViewModel.cs b/src/Maple.Core/ViewModels/Interfaces/IMediaPlayersViewModel.cs index e3cc46b..aaf68a6 100644 --- a/src/Maple.Core/ViewModels/Interfaces/IMediaPlayersViewModel.cs +++ b/src/Maple.Core/ViewModels/Interfaces/IMediaPlayersViewModel.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; - -namespace Maple.Core +namespace Maple.Core { - public interface IMediaPlayersViewModel : ILoadableViewModel, ISaveableViewModel, IDisposable + public interface IMediaPlayersViewModel { - IReadOnlyList Items { get; } } } \ No newline at end of file diff --git a/src/Maple.Core/ViewModels/Interfaces/IPlaylistsViewModel.cs b/src/Maple.Core/ViewModels/Interfaces/IPlaylistsViewModel.cs index e28ac9f..8c6acb0 100644 --- a/src/Maple.Core/ViewModels/Interfaces/IPlaylistsViewModel.cs +++ b/src/Maple.Core/ViewModels/Interfaces/IPlaylistsViewModel.cs @@ -1,7 +1,6 @@ namespace Maple.Core { - public interface IPlaylistsViewModel : ILoadableViewModel, ISaveableViewModel + public interface IPlaylistsViewModel { - void Add(); } } \ No newline at end of file diff --git a/src/Maple.Core/ViewModels/Interfaces/IUIColorsViewModel.cs b/src/Maple.Core/ViewModels/Interfaces/IUIColorsViewModel.cs index 97591bf..78e23e7 100644 --- a/src/Maple.Core/ViewModels/Interfaces/IUIColorsViewModel.cs +++ b/src/Maple.Core/ViewModels/Interfaces/IUIColorsViewModel.cs @@ -2,7 +2,7 @@ namespace Maple.Core { - public interface IUIColorsViewModel : ILoadableViewModel, ISaveableViewModel + public interface IUIColorsViewModel : ILoadableViewModel { ICommand ApplyAccentCommand { get; } ICommand ApplyPrimaryCommand { get; } diff --git a/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs b/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs index f019241..0c83557 100644 --- a/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs +++ b/src/Maple.Core/ViewModels/MediaItems/MediaItems.cs @@ -1,75 +1,12 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Maple.Domain; +using Maple.Domain; namespace Maple.Core { - public class MediaItems : ValidableBaseDataListViewModel, IMediaItemsViewModel + public class MediaItems : ValidableBaseDataListViewModel { - private readonly Func _repositoryFactory; - private readonly IMediaItemMapper _mediaItemMapper; - - protected MediaItems(ViewModelServiceContainer container, IMapleRepository repository) - : base(container, repository) - { - } - - public override bool IsLoaded - { - get { throw new NotImplementedException(); } - protected set => throw new NotImplementedException(); - } - - public override IAsyncCommand SaveCommand => throw new NotImplementedException(); - - public override IAsyncCommand LoadCommand => throw new NotImplementedException(); - - public override IAsyncCommand RefreshCommand => throw new NotImplementedException(); - - public void Add(Playlist playlist) + protected MediaItems(ViewModelServiceContainer container) + : base(container) { - var sequence = _sequenceProvider.Get(Items.Select(p => (ISequence)p).ToList()); - Add(_mediaItemMapper.GetNewMediaItem(sequence, playlist)); } - - public override Task GetCountAsync() - { - throw new NotImplementedException(); - } - - public override Task GetItemsWithKey(int[] keys) - { - throw new NotImplementedException(); - } - - public override Task SaveAsync() - { - throw new NotImplementedException(); - } - - //public override async Task GetCountAsync() - //{ - // _log.Info($"{_translationService.Translate(nameof(Resources.Loading))} {_translationService.Translate(nameof(Resources.MediaItems))}"); - // Clear(); - - // using (var context = _repositoryFactory()) - // { - // var result = await context.GetMediaItemsAsync().ConfigureAwait(true); - // AddRange(result); - // } - - // SelectedItem = Items.FirstOrDefault(); - // IsLoaded = true; - //} - - //public override async Task SaveAsync() - //{ - // _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.MediaItems))}"); - // using (var context = _repositoryFactory()) - // { - // await context.SaveAsync(this).ConfigureAwait(true); - // } - //} } } diff --git a/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayer.cs b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayer.cs index 7bf0f42..1663ad7 100644 --- a/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayer.cs +++ b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayer.cs @@ -3,7 +3,9 @@ using System.Diagnostics; using System.Linq; using System.Windows.Input; + using FluentValidation; + using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; @@ -18,7 +20,6 @@ public class MediaPlayer : ValidableBaseDataViewModel Model.IsNew; - public bool IsDeleted => Model.IsDeleted; private IMediaPlayer _player; public IMediaPlayer Player @@ -102,8 +103,8 @@ public MediaPlayer(ViewModelServiceContainer container, IMediaPlayer player, IVa _audioDevices = devices; _sequence = model.Sequence; - if (AudioDevices.Items.Count > 0) - Player.AudioDevice = AudioDevices.Items.FirstOrDefault(p => p.Name == Model.DeviceName) ?? AudioDevices[0]; + if (AudioDevices.ReadOnlyItems.Count > 0) + Player.AudioDevice = AudioDevices.ReadOnlyItems.FirstOrDefault(p => p.Name == Model.DeviceName) ?? AudioDevices[0]; Playlist = playlist; diff --git a/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs index 0424034..0d93984 100644 --- a/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs +++ b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayers.cs @@ -1,104 +1,12 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Maple.Domain; +using Maple.Domain; namespace Maple.Core { public class MediaPlayers : ValidableBaseDataListViewModel, IMediaPlayersViewModel { - private readonly Func _playerFactory; - private readonly AudioDevices _devices; - private readonly IDialogViewModel _dialog; - private readonly Func _repositoryFactory; - private readonly IMediaPlayerMapper _mediaPlayerMapper; - private readonly ILoggingNotifcationService _notificationService; - - protected MediaPlayers(ViewModelServiceContainer container, IMapleRepository repository) - : base(container, repository) - { - } - - public override bool IsLoaded - { - get { throw new NotImplementedException(); } - protected set => throw new NotImplementedException(); - } - - public override IAsyncCommand SaveCommand => throw new NotImplementedException(); - - public override IAsyncCommand LoadCommand => throw new NotImplementedException(); - - public override IAsyncCommand RefreshCommand => throw new NotImplementedException(); - - public void Add() - { - var sequence = _sequenceProvider.Get(Items.Select(p => (ISequence)p).ToList()); - Add(_mediaPlayerMapper.GetNewMediaPlayer(sequence)); - } - - public override Task GetCountAsync() - { - throw new NotImplementedException(); - } - - public override Task GetItemsWithKey(int[] keys) + protected MediaPlayers(ViewModelServiceContainer container) + : base(container) { - throw new NotImplementedException(); } - - public override Task SaveAsync() - { - throw new NotImplementedException(); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected override void Dispose(bool disposing) - { - if (Disposed) - return; - - if (disposing) - { - foreach (var player in Items) - player?.Dispose(); - - // Free any other managed objects here. - } - - // Free any unmanaged objects here. - Disposed = true; - } - - //public override async Task SaveAsync() - //{ - // _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.MediaPlayers))}"); - // using (var context = _repositoryFactory()) - // { - // await context.SaveAsync(this).ConfigureAwait(true); - // } - //} - - //public override async Task GetCountAsync() - //{ - // _notificationService.Info($"{_translationService.Translate(nameof(Resources.Loading))} {_translationService.Translate(nameof(Resources.MediaPlayers))}"); - // Clear(); - - // using (var context = _repositoryFactory()) - // { - // var main = await context.GetMainMediaPlayerAsync().ConfigureAwait(true); - - // Add(main); - // SelectedItem = main; - - // var others = await context.GetAllOptionalMediaPlayersAsync().ConfigureAwait(true); - // AddRange(others); - // } - - // IsLoaded = true; - //} } } diff --git a/src/Maple.Core/ViewModels/Playlists/Playlist.cs b/src/Maple.Core/ViewModels/Playlists/Playlist.cs index 78a98cf..b3ac333 100644 --- a/src/Maple.Core/ViewModels/Playlists/Playlist.cs +++ b/src/Maple.Core/ViewModels/Playlists/Playlist.cs @@ -7,7 +7,9 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Input; + using FluentValidation; + using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; @@ -15,7 +17,7 @@ namespace Maple.Core { [DebuggerDisplay("{Title}, {Sequence}")] - public class Playlist : ValidableBaseDataViewModel, IIsSelected, ISequence, IIdentifier, IChangeState + public class Playlist : ValidableBaseDataViewModel, IIsSelected, ISequence { private readonly IMediaItemMapper _mediaItemMapper; private readonly ISequenceService _sequenceProvider; @@ -392,8 +394,7 @@ public virtual bool CanRemove(object item) if (Items == null || Items.Count == 0) return false; - var mediaItem = item as MediaItem; - if (mediaItem == null) + if (!(item is MediaItem mediaItem)) return false; return Items.Contains(mediaItem) && !IsBusy; diff --git a/src/Maple.Core/ViewModels/Playlists/Playlists.cs b/src/Maple.Core/ViewModels/Playlists/Playlists.cs index 11e7291..9d5239b 100644 --- a/src/Maple.Core/ViewModels/Playlists/Playlists.cs +++ b/src/Maple.Core/ViewModels/Playlists/Playlists.cs @@ -1,84 +1,12 @@ -using System; -using System.Threading.Tasks; -using Maple.Domain; +using Maple.Domain; namespace Maple.Core { - public class Playlists : ValidableBaseDataListViewModel, ISaveableViewModel, IPlaylistsViewModel + public class Playlists : ValidableBaseDataListViewModel, IPlaylistsViewModel { - public override bool IsLoaded + protected Playlists(ViewModelServiceContainer container) + : base(container) { - get { throw new NotImplementedException(); } - protected set { throw new NotImplementedException(); } } - - public override IAsyncCommand SaveCommand => throw new NotImplementedException(); - - public override IAsyncCommand LoadCommand => throw new NotImplementedException(); - - public override IAsyncCommand RefreshCommand => throw new NotImplementedException(); - - protected Playlists(ViewModelServiceContainer container, IMapleRepository repository) - : base(container, repository) - { - } - - //public Playlists(ViewModelServiceContainer container, IPlaylistMapper playlistMapper, Func repositoryFactory) - // : base(container) - //{ - // _repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory), $"{nameof(repositoryFactory)} {Resources.IsRequired}"); - // _playlistMapper = playlistMapper ?? throw new ArgumentNullException(nameof(playlistMapper), $"{nameof(playlistMapper)} {Resources.IsRequired}"); - - // AddCommand = new RelayCommand(Add, CanAdd); - //} - - public void Add() - { - //Add(_playlistMapper.GetNewPlaylist()); - } - - public bool CanAdd() - { - return Items != null; - } - - public override Task GetCountAsync() - { - throw new NotImplementedException(); - } - - public override Task GetItemsWithKey(int[] keys) - { - throw new NotImplementedException(); - } - - public override Task SaveAsync() - { - throw new NotImplementedException(); - } - - //public override async Task SaveAsync() - //{ - // _log.Info($"{_translationService.Translate(nameof(Resources.Saving))} {_translationService.Translate(nameof(Resources.Playlists))}"); - // using (var context = _repositoryFactory()) - // { - // await context.SaveAsync(this).ConfigureAwait(true); - // } - //} - - //public override async Task GetCountAsync() - //{ - // _log.Info($"{_translationService.Translate(nameof(Resources.Loading))} {_translationService.Translate(nameof(Resources.Playlists))}"); - // Clear(); - - // using (var context = _repositoryFactory()) - // { - // var result = await context.GetPlaylistsAsync().ConfigureAwait(true); - // AddRange(result); - // } - - // SelectedItem = Items.FirstOrDefault(); - // IsLoaded = true; - //} } } diff --git a/src/Maple.Core/ViewModels/ViewModelServiceContainer.cs b/src/Maple.Core/ViewModels/ViewModelServiceContainer.cs index c047d07..694f811 100644 --- a/src/Maple.Core/ViewModels/ViewModelServiceContainer.cs +++ b/src/Maple.Core/ViewModels/ViewModelServiceContainer.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.Caching; + using Maple.Domain; using Maple.Localization.Properties; @@ -14,11 +15,13 @@ public class ViewModelServiceContainer public ILoggingService Log { get; } public MemoryCache Cache { get; } public CacheItemPolicy CacheItemPolicy { get; } + public IRepository Repository { get; } - public ViewModelServiceContainer(ILoggingService log, + public ViewModelServiceContainer(ILoggingService log, IRepository repository, ILoggingNotifcationService notificationService, ILocalizationService localizationService, IMessenger messenger, ISequenceService sequenceService, MemoryCache cache, CacheItemPolicy itemPolicy) { + Repository = repository ?? throw new ArgumentNullException(nameof(repository), $"{nameof(repository)} {Resources.IsRequired}"); Log = log ?? throw new ArgumentNullException(nameof(log), $"{nameof(log)} {Resources.IsRequired}"); LocalizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService), $"{nameof(localizationService)} {Resources.IsRequired}"); SequenceService = sequenceService ?? throw new ArgumentNullException(nameof(sequenceService), $"{nameof(sequenceService)} {Resources.IsRequired}"); diff --git a/src/Maple.Data/DB/CreateSeedDatabaseIfNotExists.cs b/src/Maple.Data/DB/CreateSeedDatabaseIfNotExists.cs index a514349..141dc9f 100644 --- a/src/Maple.Data/DB/CreateSeedDatabaseIfNotExists.cs +++ b/src/Maple.Data/DB/CreateSeedDatabaseIfNotExists.cs @@ -2,16 +2,15 @@ using System.Collections.Generic; using System.Data.Entity; using System.Diagnostics; + using Maple.Domain; + using SQLite.CodeFirst; namespace Maple.Data { - public class CreateSeedDatabaseIfNotExists : SqliteDropCreateDatabaseWhenModelChanges - where TContext : PlaylistContext + public class CreateSeedDatabaseIfNotExists : SqliteDropCreateDatabaseWhenModelChanges { - private const int saveThresHold = 100; - private readonly List _playlistTitles = new List() { "Memories Of A Time To Come", @@ -69,7 +68,7 @@ public CreateSeedDatabaseIfNotExists(DbModelBuilder modelBuilder, Type historyEn { } - protected override void Seed(TContext context) + protected override void Seed(MapleContext context) { if (!Debugger.IsAttached) { @@ -85,7 +84,7 @@ protected override void Seed(TContext context) context.SaveChanges(); } - private void SeedTestData(TContext context) + private void SeedTestData(MapleContext context) { context.Playlists .Add(new PlaylistModel @@ -161,15 +160,12 @@ private void SeedTestData(TContext context) UpdatedOn = DateTime.UtcNow, }); index++; - - if (index % saveThresHold == 0) - context.SaveChanges(); } } } - private void SeedMediaPlayers(TContext context) + private void SeedMediaPlayers(MapleContext context) { if (context.Mediaplayers.Find(1) == null) context.Mediaplayers diff --git a/src/Maple.Data/DB/PlaylistContext.cs b/src/Maple.Data/DB/MapleContext.cs similarity index 86% rename from src/Maple.Data/DB/PlaylistContext.cs rename to src/Maple.Data/DB/MapleContext.cs index 1801c1b..5204314 100644 --- a/src/Maple.Data/DB/PlaylistContext.cs +++ b/src/Maple.Data/DB/MapleContext.cs @@ -1,15 +1,16 @@ using System.Data.Entity; + using Maple.Domain; namespace Maple.Data { - public class PlaylistContext : DbContext + public sealed class MapleContext : DbContext { public DbSet Playlists { get; set; } public DbSet MediaItems { get; set; } public DbSet Mediaplayers { get; set; } - public PlaylistContext() + public MapleContext() : base("Main") { Configuration.ProxyCreationEnabled = false; @@ -19,7 +20,7 @@ public PlaylistContext() protected override void OnModelCreating(DbModelBuilder modelBuilder) { ModelConfiguration.Configure(modelBuilder); - Database.SetInitializer(new CreateSeedDatabaseIfNotExists(modelBuilder)); + Database.SetInitializer(new CreateSeedDatabaseIfNotExists(modelBuilder)); } protected override void Dispose(bool disposing) diff --git a/src/Maple.Data/Maple.Data.csproj b/src/Maple.Data/Maple.Data.csproj index a367c49..5cd9f56 100644 --- a/src/Maple.Data/Maple.Data.csproj +++ b/src/Maple.Data/Maple.Data.csproj @@ -73,17 +73,14 @@ Properties\SharedAssemblyInfo.cs + - - - - - - - - + + + + diff --git a/src/Maple.Data/Repository/Base/EntityFrameworkReadOnlyRepository.cs b/src/Maple.Data/Repository/Base/EntityFrameworkReadOnlyRepository.cs new file mode 100644 index 0000000..212cb50 --- /dev/null +++ b/src/Maple.Data/Repository/Base/EntityFrameworkReadOnlyRepository.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using System.Data.Entity; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; + +using Maple.Domain; + +namespace Maple.Data +{ + public abstract class EntityFrameworkReadOnlyRepository : IReadOnlyRepository + where TContext : DbContext + { + protected readonly TContext context; + + public EntityFrameworkReadOnlyRepository(TContext context) + { + this.context = context ?? throw new ArgumentNullException(nameof(context)); + } + + protected virtual IQueryable GetQueryable( + Expression> filter = null, + Func, IOrderedQueryable> orderBy = null, + string includeProperties = null, int? skip = null, int? take = null) + where TEntity : class, IEntity + { + includeProperties = includeProperties ?? string.Empty; + IQueryable query = context.Set(); + + if (filter != null) + query = query.Where(filter); + + foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + query = query.Include(includeProperty); + + if (orderBy != null) + query = orderBy(query); + + if (skip.HasValue) + query = query.Skip(skip.Value); + + if (take.HasValue) + query = query.Take(take.Value); + + return query; + } + + public virtual IEnumerable GetAll( + Func, IOrderedQueryable> orderBy = null, + string includeProperties = null, + int? skip = null, + int? take = null) + where TEntity : class, IEntity + { + return GetQueryable(null, orderBy, includeProperties, skip, take).ToList(); + } + + public virtual async Task> GetAllAsync( + Func, IOrderedQueryable> orderBy = null, + string includeProperties = null, + int? skip = null, + int? take = null) + where TEntity : class, IEntity + { + return await GetQueryable(null, orderBy, includeProperties, skip, take).ToListAsync(); + } + + public virtual IEnumerable Get( + Expression> filter = null, + Func, IOrderedQueryable> orderBy = null, + string includeProperties = null, + int? skip = null, + int? take = null) + where TEntity : class, IEntity + { + return GetQueryable(filter, orderBy, includeProperties, skip, take).ToList(); + } + + public virtual async Task> GetAsync( + Expression> filter = null, + Func, IOrderedQueryable> orderBy = null, + string includeProperties = null, + int? skip = null, + int? take = null) + where TEntity : class, IEntity + { + return await GetQueryable(filter, orderBy, includeProperties, skip, take).ToListAsync(); + } + + public virtual TEntity GetOne( + Expression> filter = null, + string includeProperties = "") + where TEntity : class, IEntity + { + return GetQueryable(filter, null, includeProperties).SingleOrDefault(); + } + + public virtual async Task GetOneAsync( + Expression> filter = null, + string includeProperties = null) + where TEntity : class, IEntity + { + return await GetQueryable(filter, null, includeProperties).SingleOrDefaultAsync(); + } + + public virtual TEntity GetFirst( + Expression> filter = null, + Func, IOrderedQueryable> orderBy = null, + string includeProperties = "") + where TEntity : class, IEntity + { + return GetQueryable(filter, orderBy, includeProperties).FirstOrDefault(); + } + + public virtual async Task GetFirstAsync( + Expression> filter = null, + Func, IOrderedQueryable> orderBy = null, + string includeProperties = null) + where TEntity : class, IEntity + { + return await GetQueryable(filter, orderBy, includeProperties).FirstOrDefaultAsync(); + } + + public virtual TEntity GetById(object id) + where TEntity : class, IEntity + { + return context.Set().Find(id); + } + + public virtual Task GetByIdAsync(object id) + where TEntity : class, IEntity + { + return context.Set().FindAsync(id); + } + + public Task> GetByIdsAsync(ICollection ids) + where TEntity : class, IEntity + { + return GetQueryable(p => ids.Contains(p.Id)).ToListAsync(); + } + + public virtual int GetCount(Expression> filter = null) + where TEntity : class, IEntity + { + return GetQueryable(filter).Count(); + } + + public virtual Task GetCountAsync(Expression> filter = null) + where TEntity : class, IEntity + { + return GetQueryable(filter).CountAsync(); + } + + public virtual bool GetExists(Expression> filter = null) + where TEntity : class, IEntity + { + return GetQueryable(filter).Any(); + } + + public virtual Task GetExistsAsync(Expression> filter = null) + where TEntity : class, IEntity + { + return GetQueryable(filter).AnyAsync(); + } + } +} \ No newline at end of file diff --git a/src/Maple.Data/Repository/Base/EntityFrameworkRepository.cs b/src/Maple.Data/Repository/Base/EntityFrameworkRepository.cs new file mode 100644 index 0000000..3fc567f --- /dev/null +++ b/src/Maple.Data/Repository/Base/EntityFrameworkRepository.cs @@ -0,0 +1,65 @@ +using System; +using System.Data.Entity; +using System.Data.Entity.Validation; +using System.Linq; + +using Maple.Domain; + +namespace Maple.Data +{ + public abstract class EntityFrameworkRepository : EntityFrameworkReadOnlyRepository, IRepository + where TContext : DbContext + { + public EntityFrameworkRepository(TContext context) + : base(context) + { + } + + public virtual void Create(TEntity entity, string createdBy = null) + where TEntity : class, IEntity + { + entity.CreatedOn = DateTime.UtcNow; + entity.CreatedBy = createdBy; + context.Set().Add(entity); + } + + public virtual void Update(TEntity entity, string modifiedBy = null) + where TEntity : class, IEntity + { + entity.UpdatedOn = DateTime.UtcNow; + entity.UpdatedBy = modifiedBy; + context.Set().Attach(entity); + context.Entry(entity).State = EntityState.Modified; + } + + public virtual void Delete(object id) + where TEntity : class, IEntity + { + var entity = context.Set().Find(id); + Delete(entity); + } + + public virtual void Delete(TEntity entity) + where TEntity : class, IEntity + { + var dbSet = context.Set(); + if (context.Entry(entity).State == EntityState.Detached) + { + dbSet.Attach(entity); + } + dbSet.Remove(entity); + } + + protected virtual void ThrowEnhancedValidationException(DbEntityValidationException e) + { + var errorMessages = e.EntityValidationErrors + .SelectMany(x => x.ValidationErrors) + .Select(x => x.ErrorMessage); + + var fullErrorMessage = string.Join("; ", errorMessages); + var exceptionMessage = string.Concat(e.Message, " The validation errors are: ", fullErrorMessage); + + throw new DbEntityValidationException(exceptionMessage, e.EntityValidationErrors); + } + } +} \ No newline at end of file diff --git a/src/Maple.Data/Repository/Base/IMediaItemRepository.cs b/src/Maple.Data/Repository/Base/IMediaItemRepository.cs deleted file mode 100644 index 9edca02..0000000 --- a/src/Maple.Data/Repository/Base/IMediaItemRepository.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Threading.Tasks; -using Maple.Domain; - -namespace Maple.Data -{ - public interface IMediaItemRepository : IMapleRepository - { - Task GetMediaItemByPlaylistIdAsync(int id); - } -} \ No newline at end of file diff --git a/src/Maple.Data/Repository/Base/IMediaPlayerRepository.cs b/src/Maple.Data/Repository/Base/IMediaPlayerRepository.cs deleted file mode 100644 index c703daa..0000000 --- a/src/Maple.Data/Repository/Base/IMediaPlayerRepository.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Maple.Domain; - -namespace Maple.Data -{ - public interface IMediaPlayerRepository : IMapleRepository - { - Task GetMainMediaPlayerAsync(); - Task> GetOptionalMediaPlayersAsync(); - } -} \ No newline at end of file diff --git a/src/Maple.Data/Repository/Base/IPlaylistRepository.cs b/src/Maple.Data/Repository/Base/IPlaylistRepository.cs deleted file mode 100644 index 8d7606b..0000000 --- a/src/Maple.Data/Repository/Base/IPlaylistRepository.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Maple.Domain; - -namespace Maple.Data -{ - public interface IPlaylistRepository : IMapleRepository - { - } -} \ No newline at end of file diff --git a/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs b/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs deleted file mode 100644 index 98f42a6..0000000 --- a/src/Maple.Data/Repository/Base/MaplePlaylistRepository.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data.Entity; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; -using Maple.Domain; - -namespace Maple.Data -{ - public abstract class MaplePlaylistRepository : IMapleRepository - where TModel : class, IBaseModel - { - public async Task SaveAsync(TModel item) - { - using (var context = new PlaylistContext()) - await SaveInternal(item, context).ConfigureAwait(false); - } - - public async Task GetByIdAsync(TKeyDataType Id) - { - using (var context = new PlaylistContext()) - return await GetByIdInternalAsync(Id, context).ConfigureAwait(false); - } - - public async Task> GetAsync() - { - using (var context = new PlaylistContext()) - return await GetInternalAsync(context).ConfigureAwait(false); - } - - public async Task> GetKeysAsync() - { - using (var context = new PlaylistContext()) - return await GetEntities(context).Select(p => p.Id).ToListAsync().ConfigureAwait(false); - } - - public async Task GetEntryCountAsync() - { - using (var context = new PlaylistContext()) - return await GetEntities(context).CountAsync().ConfigureAwait(false); - } - - protected abstract DbSet GetEntities(PlaylistContext context); - - protected virtual async Task SaveInternal(TModel item, PlaylistContext context) - { - if (item.IsNew) - Create(item, context); - else - { - if (item.IsDeleted) - { - context.Database.Log = (message) => Debug.WriteLine(message); - Delete(item, context); - } - else - await Update(item, context).ConfigureAwait(false); - } - - await context.SaveChangesAsync().ConfigureAwait(false); - } - - protected virtual void Delete(TModel item, PlaylistContext context) - { - context.Set().Remove(item); - } - - protected virtual void Create(TModel item, PlaylistContext context) - { - item.CreatedBy = System.Security.Principal.WindowsIdentity.GetCurrent().User.Value; - item.CreatedOn = DateTime.UtcNow; - - context.Set().Add(item); - } - - protected virtual async Task Update(TModel item, PlaylistContext context) - { - var entity = await GetEntities(context).FindAsync(item.Id).ConfigureAwait(false); - - if (entity == null) - return; - - item.UpdatedOn = DateTime.UtcNow; - item.UpdatedBy = System.Security.Principal.WindowsIdentity.GetCurrent().User.Value; - - - context.Entry(entity).CurrentValues.SetValues(item); - } - - protected virtual Task GetByIdInternalAsync(TKeyDataType id, PlaylistContext context) - { - return GetEntities(context).FirstOrDefaultAsync(p => EqualityComparer.Default.Equals(p.Id, id)); - } - - // override if you need to include foreignkeys - protected virtual Task> GetInternalAsync(PlaylistContext context) - { - return GetEntities(context).ToListAsync(); - } - } -} \ No newline at end of file diff --git a/src/Maple.Data/Repository/Base/UnitOfWork.cs b/src/Maple.Data/Repository/Base/UnitOfWork.cs new file mode 100644 index 0000000..0bcc7f2 --- /dev/null +++ b/src/Maple.Data/Repository/Base/UnitOfWork.cs @@ -0,0 +1,79 @@ +using System; +using System.Linq; +using System.Threading.Tasks; + +using Maple.Domain; + +namespace Maple.Data +{ + public sealed class UnitOfWork : IUnitOfWork + { + private bool _disposed; + + private MapleContext _context; + + public UnitOfWork() + : this(new MapleContext()) + { + + } + + public UnitOfWork(MapleContext context) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + } + + public void Commit() + { + _context.SaveChanges(); + } + + public async Task CommitAsync() + { + await _context.SaveChangesAsync().ConfigureAwait(false); + } + + public void Rollback() + { + _context + .ChangeTracker + .Entries() + .ToList() + .ForEach(x => x.Reload()); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + // Check to see if Dispose has already been called. + if (!_disposed) + { + // If disposing equals true, dispose all managed + // and unmanaged resources. + if (disposing) + { + // Dispose managed resources. + if (_context != null) + { + _context.Dispose(); + _context = null; + } + } + + // Call the appropriate methods to clean up + // unmanaged resources here. + // If disposing is false, + // only the following code is executed. + + + // Note disposing has been done. + _disposed = true; + } + } + } +} diff --git a/src/Maple.Data/Repository/MapleRepository.cs b/src/Maple.Data/Repository/MapleRepository.cs new file mode 100644 index 0000000..1b10ad7 --- /dev/null +++ b/src/Maple.Data/Repository/MapleRepository.cs @@ -0,0 +1,10 @@ +namespace Maple.Data +{ + public sealed class MapleRepository : EntityFrameworkRepository + { + public MapleRepository(MapleContext context) + : base(context) + { + } + } +} diff --git a/src/Maple.Data/Repository/MediaItemRepository.cs b/src/Maple.Data/Repository/MediaItemRepository.cs deleted file mode 100644 index d36e73c..0000000 --- a/src/Maple.Data/Repository/MediaItemRepository.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Data.Entity; -using System.Threading.Tasks; -using Maple.Domain; - -namespace Maple.Data -{ - public class MediaItemRepository : MaplePlaylistRepository, IMediaItemRepository - { - public async Task GetMediaItemByPlaylistIdAsync(int id) - { - using (var context = new PlaylistContext()) - return await GetMediaItemByPlaylistIdInternalAsync(id, context).ConfigureAwait(false); - } - - protected override DbSet GetEntities(PlaylistContext context) - { - return context.MediaItems; - } - - private async Task GetMediaItemByPlaylistIdInternalAsync(int id, PlaylistContext context) - { - return await GetEntities(context).FirstOrDefaultAsync(p => p.Playlist.Id == id).ConfigureAwait(false); - } - } -} diff --git a/src/Maple.Data/Repository/MediaPlayerRepository.cs b/src/Maple.Data/Repository/MediaPlayerRepository.cs deleted file mode 100644 index 3e726b2..0000000 --- a/src/Maple.Data/Repository/MediaPlayerRepository.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Collections.Generic; -using System.Data.Entity; -using System.Linq; -using System.Threading.Tasks; -using Maple.Domain; - -namespace Maple.Data -{ - public class MediaPlayerRepository : MaplePlaylistRepository, IMediaPlayerRepository - { - public async Task GetMainMediaPlayerAsync() - { - using (var context = new PlaylistContext()) - return await GetMainMediaPlayerInternal(context).ConfigureAwait(false); - } - - private async Task GetMainMediaPlayerInternal(PlaylistContext context) - { - return await GetEntities(context).Include(p => p.Playlist) - .Include(p => p.Playlist.MediaItems) - .FirstOrDefaultAsync(p => p.IsPrimary) - .ConfigureAwait(false); - } - - public async Task> GetOptionalMediaPlayersAsync() - { - using (var context = new PlaylistContext()) - return await GetOptionalMediaPlayersInternal(context).ConfigureAwait(false); - } - - private async Task> GetOptionalMediaPlayersInternal(PlaylistContext context) - { - return await GetEntities(context).Include(p => p.Playlist) - .Where(p => !p.IsPrimary) - .ToListAsync() - .ConfigureAwait(false); - } - - protected override async Task> GetInternalAsync(PlaylistContext context) - { - return await GetEntities(context).Include(p => p.Playlist).ToListAsync().ConfigureAwait(false); - } - - protected override DbSet GetEntities(PlaylistContext context) - { - return context.Mediaplayers; - } - } -} diff --git a/src/Maple.Data/Repository/PlaylistRepository.cs b/src/Maple.Data/Repository/PlaylistRepository.cs deleted file mode 100644 index 4dc87b6..0000000 --- a/src/Maple.Data/Repository/PlaylistRepository.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Collections.Generic; -using System.Data.Entity; -using System.Threading.Tasks; -using Maple.Domain; - -namespace Maple.Data -{ - public class PlaylistRepository : MaplePlaylistRepository, IPlaylistRepository - { - protected override DbSet GetEntities(PlaylistContext context) - { - return context.Playlists; - } - - protected override async Task> GetInternalAsync(PlaylistContext context) - { - return await GetEntities(context).Include(p => p.MediaItems).ToListAsync().ConfigureAwait(false); - } - } -} diff --git a/src/Maple.Domain/Enums/RepeatMode.cs b/src/Maple.Domain/Enums/RepeatMode.cs index a2638d4..8e49b95 100644 --- a/src/Maple.Domain/Enums/RepeatMode.cs +++ b/src/Maple.Domain/Enums/RepeatMode.cs @@ -1,7 +1,8 @@ namespace Maple.Domain { /// - /// defines what happens when the last of is and the is requested + /// defines what happens when the last of is and the is requested /// public enum RepeatMode { diff --git a/src/Maple.Domain/Interfaces/DataAccessLayer/IChangeState.cs b/src/Maple.Domain/Interfaces/DataAccessLayer/IChangeState.cs new file mode 100644 index 0000000..43df652 --- /dev/null +++ b/src/Maple.Domain/Interfaces/DataAccessLayer/IChangeState.cs @@ -0,0 +1,11 @@ +namespace Maple.Domain +{ + public interface IChangeState + { + /// + /// Gets a value indicating whether this instance is new. + /// + /// true if this instance is new; otherwise, false. + bool IsNew { get; } + } +} diff --git a/src/Maple.Domain/Interfaces/DataAccessLayer/IEntity.cs b/src/Maple.Domain/Interfaces/DataAccessLayer/IEntity.cs new file mode 100644 index 0000000..cba2c3d --- /dev/null +++ b/src/Maple.Domain/Interfaces/DataAccessLayer/IEntity.cs @@ -0,0 +1,19 @@ +using System; + +namespace Maple.Domain +{ + public interface IEntity : IChangeState, ISequence + { + object Id { get; } + DateTime CreatedOn { get; set; } + DateTime? UpdatedOn { get; set; } + string CreatedBy { get; set; } + string UpdatedBy { get; set; } + byte[] Version { get; set; } + } + + public interface IEntity : IEntity + { + new T Id { get; set; } + } +} diff --git a/src/Maple.Domain/Interfaces/DataAccessLayer/IReadOnlyRepository.cs b/src/Maple.Domain/Interfaces/DataAccessLayer/IReadOnlyRepository.cs new file mode 100644 index 0000000..45bead2 --- /dev/null +++ b/src/Maple.Domain/Interfaces/DataAccessLayer/IReadOnlyRepository.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace Maple.Domain +{ + public interface IReadOnlyRepository + { + IEnumerable GetAll( + Func, IOrderedQueryable> orderBy = null, + string includeProperties = null, + int? skip = null, + int? take = null) + where TEntity : class, IEntity; + + Task> GetAllAsync( + Func, IOrderedQueryable> orderBy = null, + string includeProperties = null, + int? skip = null, + int? take = null) + where TEntity : class, IEntity; + + IEnumerable Get( + Expression> filter = null, + Func, IOrderedQueryable> orderBy = null, + string includeProperties = null, + int? skip = null, + int? take = null) + where TEntity : class, IEntity; + + Task> GetAsync( + Expression> filter = null, + Func, IOrderedQueryable> orderBy = null, + string includeProperties = null, + int? skip = null, + int? take = null) + where TEntity : class, IEntity; + + TEntity GetOne( + Expression> filter = null, + string includeProperties = null) + where TEntity : class, IEntity; + + Task GetOneAsync( + Expression> filter = null, + string includeProperties = null) + where TEntity : class, IEntity; + + TEntity GetFirst( + Expression> filter = null, + Func, IOrderedQueryable> orderBy = null, + string includeProperties = null) + where TEntity : class, IEntity; + + Task GetFirstAsync( + Expression> filter = null, + Func, IOrderedQueryable> orderBy = null, + string includeProperties = null) + where TEntity : class, IEntity; + + TEntity GetById(object id) + where TEntity : class, IEntity; + + Task GetByIdAsync(object id) + where TEntity : class, IEntity; + + Task> GetByIdsAsync(ICollection ids) + where TEntity : class, IEntity; + + int GetCount(Expression> filter = null) + where TEntity : class, IEntity; + + Task GetCountAsync(Expression> filter = null) + where TEntity : class, IEntity; + + bool GetExists(Expression> filter = null) + where TEntity : class, IEntity; + + Task GetExistsAsync(Expression> filter = null) + where TEntity : class, IEntity; + } +} diff --git a/src/Maple.Domain/Interfaces/DataAccessLayer/IRepository.cs b/src/Maple.Domain/Interfaces/DataAccessLayer/IRepository.cs new file mode 100644 index 0000000..0c89b36 --- /dev/null +++ b/src/Maple.Domain/Interfaces/DataAccessLayer/IRepository.cs @@ -0,0 +1,17 @@ +namespace Maple.Domain +{ + public interface IRepository : IReadOnlyRepository + { + void Create(TEntity entity, string createdBy = null) + where TEntity : class, IEntity; + + void Update(TEntity entity, string modifiedBy = null) + where TEntity : class, IEntity; + + void Delete(object id) + where TEntity : class, IEntity; + + void Delete(TEntity entity) + where TEntity : class, IEntity; + } +} diff --git a/src/Maple.Domain/Interfaces/ISequence.cs b/src/Maple.Domain/Interfaces/DataAccessLayer/ISequence.cs similarity index 100% rename from src/Maple.Domain/Interfaces/ISequence.cs rename to src/Maple.Domain/Interfaces/DataAccessLayer/ISequence.cs diff --git a/src/Maple.Domain/Interfaces/DataAccessLayer/IUnitOfWork.cs b/src/Maple.Domain/Interfaces/DataAccessLayer/IUnitOfWork.cs new file mode 100644 index 0000000..8f69f6a --- /dev/null +++ b/src/Maple.Domain/Interfaces/DataAccessLayer/IUnitOfWork.cs @@ -0,0 +1,14 @@ +using System; +using System.Threading.Tasks; + +namespace Maple.Domain +{ + public interface IUnitOfWork : IDisposable + { + void Commit(); + + Task CommitAsync(); + + void Rollback(); + } +} diff --git a/src/Maple.Domain/Interfaces/IAudioDevice.cs b/src/Maple.Domain/Interfaces/IAudioDevice.cs index 10ca374..878abdf 100644 --- a/src/Maple.Domain/Interfaces/IAudioDevice.cs +++ b/src/Maple.Domain/Interfaces/IAudioDevice.cs @@ -11,4 +11,4 @@ public interface IAudioDevice : INotifyPropertyChanged string ToString(); } -} \ No newline at end of file +} diff --git a/src/Maple.Domain/Interfaces/IBaseModel.cs b/src/Maple.Domain/Interfaces/IBaseModel.cs deleted file mode 100644 index 6525c2d..0000000 --- a/src/Maple.Domain/Interfaces/IBaseModel.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; - -namespace Maple.Domain -{ - public interface IBaseModel - { - string CreatedBy { get; set; } - DateTime CreatedOn { get; set; } - TKeyDataType Id { get; set; } - bool IsDeleted { get; set; } - bool IsNew { get; } - byte[] RowVersion { get; set; } - int Sequence { get; set; } - string UpdatedBy { get; set; } - DateTime UpdatedOn { get; set; } - } -} \ No newline at end of file diff --git a/src/Maple.Domain/Interfaces/IChangeState.cs b/src/Maple.Domain/Interfaces/IChangeState.cs deleted file mode 100644 index bc36a0f..0000000 --- a/src/Maple.Domain/Interfaces/IChangeState.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Maple.Domain -{ - public interface IChangeState - { - /// - /// Gets a value indicating whether this instance is new. - /// - /// - /// true if this instance is new; otherwise, false. - /// - bool IsNew { get; } - /// - /// Gets a value indicating whether this instance is deleted. - /// - /// - /// true if this instance is deleted; otherwise, false. - /// - bool IsDeleted { get; } - } -} diff --git a/src/Maple.Domain/Interfaces/IIdentifier.cs b/src/Maple.Domain/Interfaces/IIdentifier.cs deleted file mode 100644 index 1c62518..0000000 --- a/src/Maple.Domain/Interfaces/IIdentifier.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Maple.Domain -{ - public interface IIdentifier - { - int Id { get; } - } -} diff --git a/src/Maple.Domain/Interfaces/ILoggingService.cs b/src/Maple.Domain/Interfaces/ILoggingService.cs deleted file mode 100644 index d5d3c25..0000000 --- a/src/Maple.Domain/Interfaces/ILoggingService.cs +++ /dev/null @@ -1,183 +0,0 @@ -using System; - -namespace Maple.Domain -{ - public interface ILoggingService - { - // - // Summary: - // Logs a message object with the log4net.Core.Level.Error level. - // - // Parameters: - // message: - // The message object to log. - // - // Remarks: - // This method first checks if this logger is ERROR enabled by comparing the level - // of this logger with the log4net.Core.Level.Error level. If this logger is ERROR - // enabled, then it converts the message object (passed as parameter) to a string - // by invoking the appropriate log4net.ObjectRenderer.IObjectRenderer. It then proceeds - // to call all the registered appenders in this logger and also higher in the hierarchy - // depending on the value of the additivity flag. - // WARNING Note that passing an System.Exception to this method will print the name - // of the System.Exception but no stack trace. To print a stack trace use the Error(object,Exception) - // form instead. - /// - /// Errors the specified message. - /// - /// The message. - void Error(object message); - // - // Summary: - // Log a message object with the log4net.Core.Level.Error level including the stack - // trace of the System.Exception passed as a parameter. - // - // Parameters: - // message: - // The message object to log. - // - // exception: - // The exception to log, including its stack trace. - // - // Remarks: - // See the Error(object) form for more detailed information. - /// - /// Errors the specified message. - /// - /// The message. - /// The exception. - void Error(object message, Exception exception); - - // - // Summary: - // Log a message object with the log4net.Core.Level.Fatal level. - // - // Parameters: - // message: - // The message object to log. - // - // Remarks: - // This method first checks if this logger is FATAL enabled by comparing the level - // of this logger with the log4net.Core.Level.Fatal level. If this logger is FATAL - // enabled, then it converts the message object (passed as parameter) to a string - // by invoking the appropriate log4net.ObjectRenderer.IObjectRenderer. It then proceeds - // to call all the registered appenders in this logger and also higher in the hierarchy - // depending on the value of the additivity flag. - // WARNING Note that passing an System.Exception to this method will print the name - // of the System.Exception but no stack trace. To print a stack trace use the Fatal(object,Exception) - // form instead. - /// - /// Fatals the specified message. - /// - /// The message. - void Fatal(object message); - // - // Summary: - // Log a message object with the log4net.Core.Level.Fatal level including the stack - // trace of the System.Exception passed as a parameter. - // - // Parameters: - // message: - // The message object to log. - // - // exception: - // The exception to log, including its stack trace. - // - // Remarks: - // See the Fatal(object) form for more detailed information. - /// - /// Fatals the specified message. - /// - /// The message. - /// The exception. - void Fatal(object message, Exception exception); - - // - // Summary: - // Logs a message object with the log4net.Core.Level.Info level. - // - // Parameters: - // message: - // The message object to log. - // - // Remarks: - // This method first checks if this logger is INFO enabled by comparing the level - // of this logger with the log4net.Core.Level.Info level. If this logger is INFO - // enabled, then it converts the message object (passed as parameter) to a string - // by invoking the appropriate log4net.ObjectRenderer.IObjectRenderer. It then proceeds - // to call all the registered appenders in this logger and also higher in the hierarchy - // depending on the value of the additivity flag. - // WARNING Note that passing an System.Exception to this method will print the name - // of the System.Exception but no stack trace. To print a stack trace use the Info(object,Exception) - // form instead. - /// - /// Informations the specified message. - /// - /// The message. - void Info(object message); - // - // Summary: - // Logs a message object with the INFO level including the stack trace of the System.Exception - // passed as a parameter. - // - // Parameters: - // message: - // The message object to log. - // - // exception: - // The exception to log, including its stack trace. - // - // Remarks: - // See the Info(object) form for more detailed information. - /// - /// Informations the specified message. - /// - /// The message. - /// The exception. - void Info(object message, Exception exception); - - // - // Summary: - // Log a message object with the log4net.Core.Level.Warn level. - // - // Parameters: - // message: - // The message object to log. - // - // Remarks: - // This method first checks if this logger is WARN enabled by comparing the level - // of this logger with the log4net.Core.Level.Warn level. If this logger is WARN - // enabled, then it converts the message object (passed as parameter) to a string - // by invoking the appropriate log4net.ObjectRenderer.IObjectRenderer. It then proceeds - // to call all the registered appenders in this logger and also higher in the hierarchy - // depending on the value of the additivity flag. - // WARNING Note that passing an System.Exception to this method will print the name - // of the System.Exception but no stack trace. To print a stack trace use the Warn(object,Exception) - // form instead. - /// - /// Warns the specified message. - /// - /// The message. - void Warn(object message); - // - // Summary: - // Log a message object with the log4net.Core.Level.Warn level including the stack - // trace of the System.Exception passed as a parameter. - // - // Parameters: - // message: - // The message object to log. - // - // exception: - // The exception to log, including its stack trace. - // - // Remarks: - // See the Warn(object) form for more detailed information. - /// - /// Warns the specified message. - /// - /// The message. - /// The exception. - void Warn(object message, Exception exception); - } -} diff --git a/src/Maple.Domain/Interfaces/IMapleRepository.cs b/src/Maple.Domain/Interfaces/IMapleRepository.cs deleted file mode 100644 index 282b0d5..0000000 --- a/src/Maple.Domain/Interfaces/IMapleRepository.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Maple.Domain -{ - public interface IMapleRepository - where TModel : class, IBaseModel - { - Task> GetAsync(); - Task GetByIdAsync(TKeyDataType Id); - - Task> GetKeysAsync(); - Task GetEntryCountAsync(); - - Task SaveAsync(TModel item); - } -} \ No newline at end of file diff --git a/src/Maple.Domain/Interfaces/IMediaItem.cs b/src/Maple.Domain/Interfaces/IMediaItem.cs index 342288d..0c4d1a7 100644 --- a/src/Maple.Domain/Interfaces/IMediaItem.cs +++ b/src/Maple.Domain/Interfaces/IMediaItem.cs @@ -2,7 +2,7 @@ namespace Maple.Domain { - public interface IMediaItem : IIsSelected, ISequence, IIdentifier, IChangeState + public interface IMediaItem : IIsSelected, ISequence { string Title { get; } string Location { get; } diff --git a/src/Maple.Domain/Interfaces/IMediaPlayer.cs b/src/Maple.Domain/Interfaces/IMediaPlayer.cs index 69eb616..91a4c34 100644 --- a/src/Maple.Domain/Interfaces/IMediaPlayer.cs +++ b/src/Maple.Domain/Interfaces/IMediaPlayer.cs @@ -7,9 +7,7 @@ public interface IMediaPlayer : IDisposable /// /// Gets a value indicating whether this instance is playing. /// - /// - /// true if this instance is playing; otherwise, false. - /// + /// true if this instance is playing; otherwise, false. bool IsPlaying { get; } /// @@ -17,10 +15,12 @@ public interface IMediaPlayer : IDisposable /// /// The item. bool Play(IMediaItem item); + /// /// Pauses this instance. /// void Pause(); + /// /// Stops this instance. /// @@ -29,53 +29,44 @@ public interface IMediaPlayer : IDisposable /// /// Determines whether this instance can stop. /// - /// - /// true if this instance can stop; otherwise, false. - /// + /// true if this instance can stop; otherwise, false. bool CanStop(); + /// /// Determines whether this instance can pause. /// - /// - /// true if this instance can pause; otherwise, false. - /// + /// true if this instance can pause; otherwise, false. bool CanPause(); + /// /// Determines whether this instance can play the specified item. /// /// The item. - /// - /// true if this instance can play the specified item; otherwise, false. - /// + /// true if this instance can play the specified item; otherwise, false. bool CanPlay(IMediaItem item); /// /// Gets or sets the volume. /// - /// - /// The volume. - /// + /// The volume. int Volume { get; set; } + /// /// Gets the volume maximum. /// - /// - /// The volume maximum. - /// + /// The volume maximum. int VolumeMax { get; } + /// /// Gets the volume minimum. /// - /// - /// The volume minimum. - /// + /// The volume minimum. int VolumeMin { get; } + /// /// Gets or sets the audio device. /// - /// - /// The audio device. - /// + /// The audio device. IAudioDevice AudioDevice { get; set; } } } diff --git a/src/Maple.Domain/Interfaces/IRangeObservableCollection.cs b/src/Maple.Domain/Interfaces/IRangeObservableCollection.cs index bdb627f..22ee68c 100644 --- a/src/Maple.Domain/Interfaces/IRangeObservableCollection.cs +++ b/src/Maple.Domain/Interfaces/IRangeObservableCollection.cs @@ -1,5 +1,4 @@ -using System.Collections; -using System.Collections.Generic; +using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Runtime.CompilerServices; @@ -9,7 +8,9 @@ namespace Maple.Domain public interface IRangeObservableCollection : IEnumerable, ICollection, INotifyPropertyChanged, IList, INotifyCollectionChanged { void AddRange(IEnumerable items); + void OnPropertyChanged([CallerMemberName] string propertyName = null); + void RemoveRange(IEnumerable items); } -} \ No newline at end of file +} diff --git a/src/Maple.Domain/Interfaces/ITranslationProvider.cs b/src/Maple.Domain/Interfaces/Providers/ITranslationProvider.cs similarity index 100% rename from src/Maple.Domain/Interfaces/ITranslationProvider.cs rename to src/Maple.Domain/Interfaces/Providers/ITranslationProvider.cs diff --git a/src/Maple.Core/Services/Localization/ILocalizationService.cs b/src/Maple.Domain/Interfaces/Services/ILocalizationService.cs similarity index 97% rename from src/Maple.Core/Services/Localization/ILocalizationService.cs rename to src/Maple.Domain/Interfaces/Services/ILocalizationService.cs index c6213f2..077f71e 100644 --- a/src/Maple.Core/Services/Localization/ILocalizationService.cs +++ b/src/Maple.Domain/Interfaces/Services/ILocalizationService.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Threading.Tasks; -namespace Maple +namespace Maple.Domain { /// /// diff --git a/src/Maple.Domain/Interfaces/ILoggingNotifcationService.cs b/src/Maple.Domain/Interfaces/Services/ILoggingNotifcationService.cs similarity index 92% rename from src/Maple.Domain/Interfaces/ILoggingNotifcationService.cs rename to src/Maple.Domain/Interfaces/Services/ILoggingNotifcationService.cs index 806f4b0..9d0e4c1 100644 --- a/src/Maple.Domain/Interfaces/ILoggingNotifcationService.cs +++ b/src/Maple.Domain/Interfaces/Services/ILoggingNotifcationService.cs @@ -5,12 +5,15 @@ namespace Maple.Domain /// /// forwards user friendly messages to the UI and to a /// - /// + /// public interface ILoggingNotifcationService { void Info(object message); + void Warn(object message); + void Error(object message, Exception exception); + void Fatal(object message, Exception exception); } -} \ No newline at end of file +} diff --git a/src/Maple.Domain/Interfaces/Services/ILoggingService.cs b/src/Maple.Domain/Interfaces/Services/ILoggingService.cs new file mode 100644 index 0000000..4df1abb --- /dev/null +++ b/src/Maple.Domain/Interfaces/Services/ILoggingService.cs @@ -0,0 +1,139 @@ +using System; + +namespace Maple.Domain +{ + public interface ILoggingService + { + // Summary: Logs a message object with the log4net.Core.Level.Error level. + // + // Parameters: message: The message object to log. + // + // Remarks: This method first checks if this logger is ERROR enabled by comparing the level + // of this logger with the log4net.Core.Level.Error level. If this logger is ERROR enabled, + // then it converts the message object (passed as parameter) to a string by invoking the + // appropriate log4net.ObjectRenderer.IObjectRenderer. It then proceeds to call all the + // registered appenders in this logger and also higher in the hierarchy depending on the + // value of the additivity flag. WARNING Note that passing an System.Exception to this method + // will print the name of the System.Exception but no stack trace. To print a stack trace use + // the Error(object,Exception) form instead. + /// + /// Errors the specified message. + /// + /// The message. + void Error(object message); + + // Summary: Log a message object with the log4net.Core.Level.Error level including the stack + // trace of the System.Exception passed as a parameter. + // + // Parameters: message: The message object to log. + // + // exception: The exception to log, including its stack trace. + // + // Remarks: See the Error(object) form for more detailed information. + /// + /// Errors the specified message. + /// + /// The message. + /// The exception. + void Error(object message, Exception exception); + + // Summary: Log a message object with the log4net.Core.Level.Fatal level. + // + // Parameters: message: The message object to log. + // + // Remarks: This method first checks if this logger is FATAL enabled by comparing the level + // of this logger with the log4net.Core.Level.Fatal level. If this logger is FATAL enabled, + // then it converts the message object (passed as parameter) to a string by invoking the + // appropriate log4net.ObjectRenderer.IObjectRenderer. It then proceeds to call all the + // registered appenders in this logger and also higher in the hierarchy depending on the + // value of the additivity flag. WARNING Note that passing an System.Exception to this method + // will print the name of the System.Exception but no stack trace. To print a stack trace use + // the Fatal(object,Exception) form instead. + /// + /// Fatals the specified message. + /// + /// The message. + void Fatal(object message); + + // Summary: Log a message object with the log4net.Core.Level.Fatal level including the stack + // trace of the System.Exception passed as a parameter. + // + // Parameters: message: The message object to log. + // + // exception: The exception to log, including its stack trace. + // + // Remarks: See the Fatal(object) form for more detailed information. + /// + /// Fatals the specified message. + /// + /// The message. + /// The exception. + void Fatal(object message, Exception exception); + + // Summary: Logs a message object with the log4net.Core.Level.Info level. + // + // Parameters: message: The message object to log. + // + // Remarks: This method first checks if this logger is INFO enabled by comparing the level of + // this logger with the log4net.Core.Level.Info level. If this logger is INFO enabled, then + // it converts the message object (passed as parameter) to a string by invoking the + // appropriate log4net.ObjectRenderer.IObjectRenderer. It then proceeds to call all the + // registered appenders in this logger and also higher in the hierarchy depending on the + // value of the additivity flag. WARNING Note that passing an System.Exception to this method + // will print the name of the System.Exception but no stack trace. To print a stack trace use + // the Info(object,Exception) form instead. + /// + /// Informations the specified message. + /// + /// The message. + void Info(object message); + + // Summary: Logs a message object with the INFO level including the stack trace of the + // System.Exception passed as a parameter. + // + // Parameters: message: The message object to log. + // + // exception: The exception to log, including its stack trace. + // + // Remarks: See the Info(object) form for more detailed information. + /// + /// Informations the specified message. + /// + /// The message. + /// The exception. + void Info(object message, Exception exception); + + // Summary: Log a message object with the log4net.Core.Level.Warn level. + // + // Parameters: message: The message object to log. + // + // Remarks: This method first checks if this logger is WARN enabled by comparing the level of + // this logger with the log4net.Core.Level.Warn level. If this logger is WARN enabled, then + // it converts the message object (passed as parameter) to a string by invoking the + // appropriate log4net.ObjectRenderer.IObjectRenderer. It then proceeds to call all the + // registered appenders in this logger and also higher in the hierarchy depending on the + // value of the additivity flag. WARNING Note that passing an System.Exception to this method + // will print the name of the System.Exception but no stack trace. To print a stack trace use + // the Warn(object,Exception) form instead. + /// + /// Warns the specified message. + /// + /// The message. + void Warn(object message); + + // Summary: Log a message object with the log4net.Core.Level.Warn level including the stack + // trace of the System.Exception passed as a parameter. + // + // Parameters: message: The message object to log. + // + // exception: The exception to log, including its stack trace. + // + // Remarks: See the Warn(object) form for more detailed information. + /// + /// Warns the specified message. + /// + /// The message. + /// The exception. + void Warn(object message, Exception exception); + } +} diff --git a/src/Maple.Domain/Interfaces/ISequenceService.cs b/src/Maple.Domain/Interfaces/Services/ISequenceService.cs similarity index 100% rename from src/Maple.Domain/Interfaces/ISequenceService.cs rename to src/Maple.Domain/Interfaces/Services/ISequenceService.cs diff --git a/src/Maple.Domain/Interfaces/IVersionService.cs b/src/Maple.Domain/Interfaces/Services/IVersionService.cs similarity index 98% rename from src/Maple.Domain/Interfaces/IVersionService.cs rename to src/Maple.Domain/Interfaces/Services/IVersionService.cs index b6a4bd1..8e69375 100644 --- a/src/Maple.Domain/Interfaces/IVersionService.cs +++ b/src/Maple.Domain/Interfaces/Services/IVersionService.cs @@ -4,4 +4,4 @@ public interface IVersionService { string Get(); } -} \ No newline at end of file +} diff --git a/src/Maple.Domain/Maple.Domain.csproj b/src/Maple.Domain/Maple.Domain.csproj index a574d80..e21a2ac 100644 --- a/src/Maple.Domain/Maple.Domain.csproj +++ b/src/Maple.Domain/Maple.Domain.csproj @@ -53,26 +53,29 @@ + + + + + - - - + + - - - + + - - - - - + + + + + \ No newline at end of file diff --git a/src/Maple.Domain/Models/Base/BaseModel.cs b/src/Maple.Domain/Models/Base/BaseModel.cs deleted file mode 100644 index 158a91c..0000000 --- a/src/Maple.Domain/Models/Base/BaseModel.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; - -namespace Maple.Domain -{ - public abstract class BaseModel : IBaseModel - { - [Key] - [Column(Order = 1)] - public TKeyDataType Id { get; set; } - [Column(Order = 2)] - public int Sequence { get; set; } - - public DateTime CreatedOn { get; set; } - public string CreatedBy { get; set; } - - public DateTime UpdatedOn { get; set; } - public string UpdatedBy { get; set; } - - [Timestamp] - public byte[] RowVersion { get; set; } - - [NotMapped] - public bool IsDeleted { get; set; } - - [NotMapped] - public bool IsNew => EqualityComparer.Default.Equals(Id, default(TKeyDataType)); - } -} diff --git a/src/Maple.Domain/Models/Base/Entity.cs b/src/Maple.Domain/Models/Base/Entity.cs new file mode 100644 index 0000000..5c28e8c --- /dev/null +++ b/src/Maple.Domain/Models/Base/Entity.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Maple.Domain +{ + public abstract class Entity : IEntity + { + [Key] + [Column(Order = 1)] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public T Id { get; set; } + + object IEntity.Id => Id; + + private DateTime? createdDate; + [DataType(DataType.DateTime)] + public DateTime CreatedOn + { + get { return createdDate ?? DateTime.UtcNow; } + set { createdDate = value; } + } + + [DataType(DataType.DateTime)] + public DateTime? UpdatedOn { get; set; } + + public string CreatedBy { get; set; } + + public string UpdatedBy { get; set; } + + [Column(Order = 2)] + public int Sequence { get; set; } + + [Timestamp] + public byte[] Version { get; set; } + + [NotMapped] + public bool IsNew => EqualityComparer.Default.Equals(Id, default(T)); + + [NotMapped] + public bool IsDeleted { get; set; } + } +} diff --git a/src/Maple.Domain/Models/MediaItemModel.cs b/src/Maple.Domain/Models/MediaItemModel.cs index 4a4e455..00ab215 100644 --- a/src/Maple.Domain/Models/MediaItemModel.cs +++ b/src/Maple.Domain/Models/MediaItemModel.cs @@ -5,7 +5,7 @@ namespace Maple.Domain { [DebuggerDisplay("{Title}, {Sequence}")] - public class MediaItemModel : BaseModel + public class MediaItemModel : Entity { public int PlaylistId { get; set; } [ForeignKey(nameof(PlaylistId))] @@ -15,6 +15,7 @@ public class MediaItemModel : BaseModel /// Ticks /// public long Duration { get; set; } + public int PrivacyStatus { get; set; } public int MediaItemType { get; set; } public string Description { get; set; } @@ -22,6 +23,7 @@ public class MediaItemModel : BaseModel [Required] [MaxLength(50)] public string Title { get; set; } + [Required] [MaxLength(2048)] public string Location { get; set; } diff --git a/src/Maple.Domain/Models/MediaPlayerModel.cs b/src/Maple.Domain/Models/MediaPlayerModel.cs index 1dc9b67..06b4b08 100644 --- a/src/Maple.Domain/Models/MediaPlayerModel.cs +++ b/src/Maple.Domain/Models/MediaPlayerModel.cs @@ -5,7 +5,7 @@ namespace Maple.Domain { [DebuggerDisplay("{Name}, {DeviceName}, {Sequence}")] - public class MediaPlayerModel : BaseModel + public class MediaPlayerModel : Entity { public int PlaylistId { get; set; } [ForeignKey(nameof(PlaylistId))] @@ -13,6 +13,7 @@ public class MediaPlayerModel : BaseModel [MaxLength(100)] public string DeviceName { get; set; } + public bool IsPrimary { get; set; } [Required] diff --git a/src/Maple.Domain/Models/PlaylistModel.cs b/src/Maple.Domain/Models/PlaylistModel.cs index df04ac2..82d9228 100644 --- a/src/Maple.Domain/Models/PlaylistModel.cs +++ b/src/Maple.Domain/Models/PlaylistModel.cs @@ -7,7 +7,7 @@ namespace Maple.Domain // tutorial http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx [DebuggerDisplay("{Title}, {SelectedItem}, {Sequence}")] - public class PlaylistModel : BaseModel + public class PlaylistModel : Entity { private ICollection _mediaItems; public virtual ICollection MediaItems @@ -18,6 +18,7 @@ public virtual ICollection MediaItems [MaxLength(100)] public string Description { get; set; } + public string Location { get; set; } public bool IsShuffeling { get; set; } public int PrivacyStatus { get; set; } @@ -26,6 +27,5 @@ public virtual ICollection MediaItems [Required] [MaxLength(50)] public string Title { get; set; } - } } diff --git a/src/Maple.Domain/Properties/AssemblyInfo.cs b/src/Maple.Domain/Properties/AssemblyInfo.cs index 405721d..e01a489 100644 --- a/src/Maple.Domain/Properties/AssemblyInfo.cs +++ b/src/Maple.Domain/Properties/AssemblyInfo.cs @@ -1,9 +1,7 @@ using System.Reflection; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. +// General Information about an assembly is controlled through the following set of attributes. +// Change these attribute values to modify the information associated with an assembly. [assembly: AssemblyTitle("Maple.Interfaces")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] - diff --git a/src/Maple/App.xaml.cs b/src/Maple/App.xaml.cs index b2e5b0e..59fd81a 100644 --- a/src/Maple/App.xaml.cs +++ b/src/Maple/App.xaml.cs @@ -159,16 +159,13 @@ private async Task LoadUpdates(ILoggingService log) private IList LoadApplicationData() { - return new List((_container.Resolve>()).ToArray().Select(p => p.GetCountAsync())); + //return new List((_container.Resolve>()).ToArray().Select(p => p.GetCountAsync())); } private async Task SaveState() { var log = _container.Resolve(); log.Info(Localization.Properties.Resources.SavingState); - var tasks = new List(_container.Resolve>().ToArray().Select(p => p.SaveAsync())); - - await Task.WhenAll(tasks).ConfigureAwait(true); log.Info(Localization.Properties.Resources.SavedState); } diff --git a/src/Maple/DependencyInjectionFactory.cs b/src/Maple/DependencyInjectionFactory.cs index dc22a04..9bce2d8 100644 --- a/src/Maple/DependencyInjectionFactory.cs +++ b/src/Maple/DependencyInjectionFactory.cs @@ -1,6 +1,9 @@ using System.Threading.Tasks; + using DryIoc; + using FluentValidation; + using Maple.Core; using Maple.Data; using Maple.Domain; @@ -41,10 +44,10 @@ void RegisterViewModels() // TODO register disposeables // save-/loadable ViewModels - c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(ISaveableViewModel), typeof(IPlaylistsViewModel) }, typeof(Playlists), Reuse.Singleton); - c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(ISaveableViewModel), typeof(IMediaPlayersViewModel) }, typeof(MediaPlayers), Reuse.Singleton, setup: Setup.With(allowDisposableTransient: true)); - c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(ISaveableViewModel), typeof(ICultureViewModel) }, typeof(Cultures), Reuse.Singleton); - c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(ISaveableViewModel), typeof(IUIColorsViewModel) }, typeof(UIColorsViewModel), Reuse.Singleton); + c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(IPlaylistsViewModel) }, typeof(Playlists), Reuse.Singleton); + c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(IMediaPlayersViewModel) }, typeof(MediaPlayers), Reuse.Singleton, setup: Setup.With(allowDisposableTransient: true)); + c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(ICultureViewModel) }, typeof(Cultures), Reuse.Singleton); + c.RegisterMany(new[] { typeof(ILoadableViewModel), typeof(IUIColorsViewModel) }, typeof(UIColorsViewModel), Reuse.Singleton); //generic ViewModels c.Register(Reuse.Singleton, setup: Setup.With(allowDisposableTransient: true)); @@ -65,15 +68,11 @@ void RegisterServices() { c.Register(setup: Setup.With(allowDisposableTransient: true)); c.Register(Reuse.Singleton); - c.Register(Reuse.Singleton, setup: Setup.With(allowDisposableTransient: true)); + c.Register(Reuse.Singleton, setup: Setup.With(allowDisposableTransient: true)); c.Register(Reuse.Singleton); c.Register(Reuse.Singleton); - c.Register(Reuse.Transient, setup: Setup.With(allowDisposableTransient: true)); - - c.Register(Reuse.Singleton); - c.Register(Reuse.Singleton); - c.Register(Reuse.Singleton); + c.Register(Reuse.Transient, setup: Setup.With(allowDisposableTransient: true)); c.Register(); c.Register(); diff --git a/src/Maple/Shell.xaml.cs b/src/Maple/Shell.xaml.cs index 5a1e6bc..a60acb0 100644 --- a/src/Maple/Shell.xaml.cs +++ b/src/Maple/Shell.xaml.cs @@ -1,6 +1,8 @@ using System; using System.Windows.Input; + using Maple.Core; +using Maple.Domain; namespace Maple { diff --git a/src/Maple/SplashScreen.xaml.cs b/src/Maple/SplashScreen.xaml.cs index b6793c2..ca1ce62 100644 --- a/src/Maple/SplashScreen.xaml.cs +++ b/src/Maple/SplashScreen.xaml.cs @@ -1,11 +1,14 @@ using System; + using Maple.Core; +using Maple.Domain; namespace Maple { public partial class SplashScreen : IoCWindow { - public SplashScreen(ILocalizationService manager, IMessenger messenger, ISplashScreenViewModel datacontext) : base(manager, messenger) + public SplashScreen(ILocalizationService manager, IMessenger messenger, ISplashScreenViewModel datacontext) + : base(manager, messenger) { DataContext = datacontext ?? throw new ArgumentNullException(nameof(datacontext), $"{nameof(datacontext)} {Localization.Properties.Resources.IsRequired}"); diff --git a/src/Maple/UI/Base/IIocFrameworkElement.cs b/src/Maple/UI/Base/IIocFrameworkElement.cs index 0724ec1..bc2bef2 100644 --- a/src/Maple/UI/Base/IIocFrameworkElement.cs +++ b/src/Maple/UI/Base/IIocFrameworkElement.cs @@ -1,16 +1,9 @@ -namespace Maple.Core +using Maple.Domain; + +namespace Maple.Core { - /// - /// - /// public interface IIocFrameworkElement { - /// - /// Gets the translation manager. - /// - /// - /// The translation manager. - /// ILocalizationService TranslationManager { get; } } } diff --git a/src/Maple/UI/Base/IocUserControl.cs b/src/Maple/UI/Base/IocUserControl.cs index b32b157..96a02d4 100644 --- a/src/Maple/UI/Base/IocUserControl.cs +++ b/src/Maple/UI/Base/IocUserControl.cs @@ -1,6 +1,8 @@ using System.Diagnostics; using System.Windows.Controls; + using Maple.Core; +using Maple.Domain; namespace Maple { diff --git a/src/Maple/UI/IoCResourceDictionary.cs b/src/Maple/UI/IoCResourceDictionary.cs index 127cfe2..61bf261 100644 --- a/src/Maple/UI/IoCResourceDictionary.cs +++ b/src/Maple/UI/IoCResourceDictionary.cs @@ -1,6 +1,8 @@ using System; using System.Diagnostics; + using Maple.Core; +using Maple.Domain; namespace Maple { diff --git a/src/Maple/UI/MarkupExtensions/BrushRoundConverter.cs b/src/Maple/UI/MarkupExtensions/BrushRoundConverter.cs index 19f812f..38a15b6 100644 --- a/src/Maple/UI/MarkupExtensions/BrushRoundConverter.cs +++ b/src/Maple/UI/MarkupExtensions/BrushRoundConverter.cs @@ -13,8 +13,7 @@ public class BrushRoundConverter : ConverterMarkupExtension public override object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - var solidColorBrush = value as SolidColorBrush; - if (solidColorBrush == null) + if (!(value is SolidColorBrush solidColorBrush)) return null; var color = solidColorBrush.Color; diff --git a/src/Maple/UI/MarkupExtensions/TranslationExtension.cs b/src/Maple/UI/MarkupExtensions/TranslationExtension.cs index ff79a2e..847c28b 100644 --- a/src/Maple/UI/MarkupExtensions/TranslationExtension.cs +++ b/src/Maple/UI/MarkupExtensions/TranslationExtension.cs @@ -4,7 +4,9 @@ using System.Windows.Data; using System.Windows.Markup; using System.Xaml; + using Maple.Core; +using Maple.Domain; namespace Maple { diff --git a/src/Maple/UI/UserControls/MediaPlayerPage.xaml.cs b/src/Maple/UI/UserControls/MediaPlayerPage.xaml.cs index 3a0a77f..19b9743 100644 --- a/src/Maple/UI/UserControls/MediaPlayerPage.xaml.cs +++ b/src/Maple/UI/UserControls/MediaPlayerPage.xaml.cs @@ -1,4 +1,6 @@ -namespace Maple +using Maple.Domain; + +namespace Maple { public partial class MediaPlayerPage { diff --git a/src/Maple/UI/UserControls/MediaPlayersPage.xaml.cs b/src/Maple/UI/UserControls/MediaPlayersPage.xaml.cs index 6a4dd8b..1d32ec7 100644 --- a/src/Maple/UI/UserControls/MediaPlayersPage.xaml.cs +++ b/src/Maple/UI/UserControls/MediaPlayersPage.xaml.cs @@ -1,4 +1,6 @@ -namespace Maple +using Maple.Domain; + +namespace Maple { public partial class MediaPlayersPage { diff --git a/src/Maple/UI/UserControls/Options/ColorOptionsPage.xaml.cs b/src/Maple/UI/UserControls/Options/ColorOptionsPage.xaml.cs index 6fe0111..6095987 100644 --- a/src/Maple/UI/UserControls/Options/ColorOptionsPage.xaml.cs +++ b/src/Maple/UI/UserControls/Options/ColorOptionsPage.xaml.cs @@ -1,4 +1,6 @@ -namespace Maple +using Maple.Domain; + +namespace Maple { public partial class ColorOptionsPage { diff --git a/src/Maple/UI/UserControls/Options/OptionsPage.xaml.cs b/src/Maple/UI/UserControls/Options/OptionsPage.xaml.cs index abb8903..86880c5 100644 --- a/src/Maple/UI/UserControls/Options/OptionsPage.xaml.cs +++ b/src/Maple/UI/UserControls/Options/OptionsPage.xaml.cs @@ -1,4 +1,6 @@ -namespace Maple +using Maple.Domain; + +namespace Maple { public partial class OptionsPage { diff --git a/src/Maple/UI/UserControls/Playlist/NewPlaylistOptionsPage.xaml.cs b/src/Maple/UI/UserControls/Playlist/NewPlaylistOptionsPage.xaml.cs index ef9b3e8..9b189e0 100644 --- a/src/Maple/UI/UserControls/Playlist/NewPlaylistOptionsPage.xaml.cs +++ b/src/Maple/UI/UserControls/Playlist/NewPlaylistOptionsPage.xaml.cs @@ -1,4 +1,6 @@ -namespace Maple +using Maple.Domain; + +namespace Maple { public partial class NewPlaylistOptionsPage { diff --git a/src/Maple/UI/UserControls/Playlist/NewPlaylistPage.xaml.cs b/src/Maple/UI/UserControls/Playlist/NewPlaylistPage.xaml.cs index 9464c19..5fa8737 100644 --- a/src/Maple/UI/UserControls/Playlist/NewPlaylistPage.xaml.cs +++ b/src/Maple/UI/UserControls/Playlist/NewPlaylistPage.xaml.cs @@ -1,4 +1,6 @@ -namespace Maple +using Maple.Domain; + +namespace Maple { public partial class NewPlaylistPage { diff --git a/src/Maple/UI/UserControls/Playlist/PlaylistsPage.xaml.cs b/src/Maple/UI/UserControls/Playlist/PlaylistsPage.xaml.cs index af99f71..3e8c742 100644 --- a/src/Maple/UI/UserControls/Playlist/PlaylistsPage.xaml.cs +++ b/src/Maple/UI/UserControls/Playlist/PlaylistsPage.xaml.cs @@ -1,4 +1,6 @@ -namespace Maple +using Maple.Domain; + +namespace Maple { public partial class PlaylistsPage { diff --git a/src/Maple/ViewModels/Navigation/Scenes.cs b/src/Maple/ViewModels/Navigation/Scenes.cs index cfb4d97..c47f480 100644 --- a/src/Maple/ViewModels/Navigation/Scenes.cs +++ b/src/Maple/ViewModels/Navigation/Scenes.cs @@ -1,8 +1,8 @@ using System; -using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Windows.Input; + using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; @@ -148,11 +148,6 @@ public Scenes(ILocalizationService manager, ILoggingService log, IMessenger mess AddRange(content); SelectedItem = this[0]; - - using (View.DeferRefresh()) - { - View.SortDescriptions.Add(new SortDescription(nameof(Scene.Sequence), ListSortDirection.Ascending)); - } } InitializeCommands(); diff --git a/src/Maple/ViewModels/ShellViewModel.cs b/src/Maple/ViewModels/ShellViewModel.cs index f4e21f1..5837fa6 100644 --- a/src/Maple/ViewModels/ShellViewModel.cs +++ b/src/Maple/ViewModels/ShellViewModel.cs @@ -1,5 +1,7 @@ using System; + using Maple.Core; +using Maple.Domain; using Maple.Localization.Properties; namespace Maple From 9c79119ee3bb3806abcf83c02234371591f1eae6 Mon Sep 17 00:00:00 2001 From: Insire Date: Sun, 6 May 2018 19:02:53 +0200 Subject: [PATCH 14/16] added SonarAnalyzer.CSharp nuget packages, fixed some of the upcoming issues --- src/Maple.Core/Commands/RelayCommand.cs | 2 +- src/Maple.Core/DiagnosticReport.cs | 499 -------------- src/Maple.Core/DiagnosticReportType.cs | 48 -- src/Maple.Core/DispatcherFactory.cs | 48 -- src/Maple.Core/DynamicDictionary.cs | 219 ------ src/Maple.Core/Ensure.cs | 17 +- .../Extensions/GenericExtensions.cs | 241 ------- src/Maple.Core/Extensions/LinqExtensions.cs | 2 +- src/Maple.Core/Extensions/StringExtensions.cs | 650 +----------------- src/Maple.Core/Helpers/NetworkHelper.cs | 84 --- src/Maple.Core/Helpers/ProcessHelper.cs | 117 ---- src/Maple.Core/Maple.Core.csproj | 13 +- .../Observables/Base/ObservableObject.cs | 2 +- .../Observables/NotifyTaskCompletion.cs | 2 +- .../Observables/RangeObservableCollection.cs | 41 +- .../ViewModels/BaseDataListViewModel.cs | 44 +- .../ViewModels/BaseDataViewModel.cs | 27 +- .../ViewModels/BaseListViewModel.cs | 4 +- .../ValidableBaseDataListViewModel.cs | 2 +- .../ViewModels/ValidableBaseDataViewModel.cs | 14 +- .../Observables/ViewModels/ViewModel.cs | 4 +- .../Virtualization/VirtualizationViewModel.cs | 10 +- .../VirtualizingCollectionViewSource.cs | 9 +- src/Maple.Core/ProcessExecutionResult.cs | 79 --- .../Services/Caching/ICachingService.cs | 2 +- .../Services/Caching/MemoryCacheService.cs | 13 +- .../Caching/SimpleStaticCacheService.cs | 4 +- .../Services/Caching/WeakReferenceCache.cs | 7 +- .../Services/Localization/LocalizationDTO.cs | 4 +- .../Services/Logging/DetailLoggingService.cs | 81 --- .../Services/Logging/LoggingService.cs | 4 +- .../Services/Mapping/Base/IBaseMapper.cs | 2 +- .../Services/Mapping/MediaItemMapper.cs | 17 +- .../Services/Mapping/MediaPlayerMapper.cs | 5 +- .../Services/Mapping/PlaylistMapper.cs | 12 +- .../Services/Validation/Base/BaseValidator.cs | 2 +- .../Services/Validation/MediaItemValidator.cs | 2 +- .../Validation/MediaPlayerValidator.cs | 2 +- .../Services/Validation/PlaylistValidator.cs | 2 +- .../Services/Validation/PlaylistsValidator.cs | 2 +- .../Dialogs/Base/DialogBaseViewModel.cs | 12 +- .../IO/FileBrowserContentDialogViewModel.cs | 5 +- .../IO/FolderBrowserContentDialogViewModel.cs | 5 +- .../ViewModels/Dialogs/DialogViewModel.cs | 7 +- .../ViewModels/MediaItems/CreateMediaItem.cs | 5 +- .../ViewModels/MediaPlayer/Base/BasePlayer.cs | 2 +- .../ViewModels/MediaPlayer/MediaPlayer.cs | 3 +- .../ViewModels/Playlists/Playlist.cs | 24 +- .../ViewModels/Settings/Cultures.cs | 6 +- .../ViewModels/SplashScreenViewModel.cs | 11 +- .../ViewModels/StatusbarViewModel.cs | 1 + .../DB/CreateSeedDatabaseIfNotExists.cs | 95 --- src/Maple.Data/DB/MapleContext.cs | 5 - src/Maple.Data/Maple.Data.csproj | 14 +- .../Base/EntityFrameworkReadOnlyRepository.cs | 30 +- .../Base/EntityFrameworkRepository.cs | 2 +- src/Maple.Data/Repository/Base/UnitOfWork.cs | 2 + src/Maple.Domain/Enums/PlaybackState.cs | 2 +- src/Maple.Domain/Interfaces/IMediaPlayer.cs | 4 +- .../Interfaces/IRangeObservableCollection.cs | 2 +- src/Maple.Domain/Maple.Domain.csproj | 7 +- src/Maple.Domain/Models/Base/Entity.cs | 2 +- .../Maple.Localization.csproj | 7 +- src/Maple.Test/DiagnosticReportTests.cs | 269 -------- src/Maple.Test/DynamicDictionaryTests.cs | 267 ------- src/Maple.Test/Maple.Test.csproj | 5 +- .../TestUtils/ContainerContextExtensions.cs | 5 +- src/Maple.Youtube/YoutubeApi.cs | 10 +- src/Maple/DependencyInjectionFactory.cs | 3 +- .../MarkupExtensions/TranslationExtension.cs | 2 +- 70 files changed, 207 insertions(+), 2946 deletions(-) delete mode 100644 src/Maple.Core/DiagnosticReport.cs delete mode 100644 src/Maple.Core/DiagnosticReportType.cs delete mode 100644 src/Maple.Core/DispatcherFactory.cs delete mode 100644 src/Maple.Core/DynamicDictionary.cs delete mode 100644 src/Maple.Core/Extensions/GenericExtensions.cs delete mode 100644 src/Maple.Core/Helpers/NetworkHelper.cs delete mode 100644 src/Maple.Core/Helpers/ProcessHelper.cs delete mode 100644 src/Maple.Core/ProcessExecutionResult.cs delete mode 100644 src/Maple.Core/Services/Logging/DetailLoggingService.cs delete mode 100644 src/Maple.Test/DiagnosticReportTests.cs delete mode 100644 src/Maple.Test/DynamicDictionaryTests.cs diff --git a/src/Maple.Core/Commands/RelayCommand.cs b/src/Maple.Core/Commands/RelayCommand.cs index f5e5b5d..e998960 100644 --- a/src/Maple.Core/Commands/RelayCommand.cs +++ b/src/Maple.Core/Commands/RelayCommand.cs @@ -103,7 +103,7 @@ public bool CanExecute(object parameter) return true; if (parameter == null && typeof(T).IsValueType) - return _canExecute.Invoke(default(T)); + return _canExecute.Invoke(default); if (parameter == null || parameter is T) return (_canExecute.Invoke((T)parameter)); diff --git a/src/Maple.Core/DiagnosticReport.cs b/src/Maple.Core/DiagnosticReport.cs deleted file mode 100644 index 3572867..0000000 --- a/src/Maple.Core/DiagnosticReport.cs +++ /dev/null @@ -1,499 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Text; -using Humanizer; -using Microsoft.Win32; - -namespace Maple.Core -{ - - /// - /// A helper class for generating a report containing details related to - /// System, Process, Assemblies, Network and Environment - /// on which the application executes. - /// - public static class DiagnosticReport - { - private const char Pipe = '|'; - private const char Dot = '.'; - private const char Dash = '-'; - private const char Space = ' '; - private const char Colon = ':'; - private static readonly string NewLine = Environment.NewLine; - private static readonly string LinePrefix = Pipe + "\t"; - - private static readonly Action[] Actions = - { - AddSystem, - AddProcess, - AddDrives, - AddAssemblies, - AddNetworking - }; - - private static readonly string[] SystemHeaders = - { - "OS", - "64Bit OS", - "CLR Runtime", - "FQDN", - "Machine Name", - "Installed RAM", - "CPU", - "CPU Core Count", - "User", - "System Directory", - "Current Directory" - }; - - private static readonly string[] ProcessHeaders = - { - "Id", - "Name", - "Started", - "Loaded In", - "Optimized", - "64Bit Process", - "Large Address Aware", - "Module Name", - "Module File Name", - "Product Name", - "Original File Name", - "File Name", - "File Version", - "Product Version", - "Language", - "Copyright", - "WorkingSet", - "Interactive", - "CommandLine" - }; - - private static readonly string[] DrivesHeaders = - { - "Name", "Type", "Format", "Label", "Capacity(GB)", "Free(GB)", "Available(GB)" - }; - - private static readonly string[] AssemblyHeaders = - { - "Name", "GAC", "64Bit", "Optimized", "Framework", "Location", "CodeBase" - }; - - /// - /// Returns the details related to System, Process, Assemblies - /// and Environment on which the application executes. - /// - public static string Generate(DiagnosticReportType type = DiagnosticReportType.Full) - { - try - { - return GenerateImpl(type); - } - catch (Exception e) - { - return $"Unable to generate the Diagnostic Report. Error:{NewLine}\t{e}"; - } - } - - private static string GenerateImpl(DiagnosticReportType type) - { - var sw = Stopwatch.StartNew(); - - var builder = new StringBuilder(); - for (var i = 0; i < Actions.Length; i++) - { - var enabled = ((int)type & (1 << i)) != 0; - if (enabled) { Actions[i](builder); } - } - - sw.Stop(); - - builder.Insert(0, $"/{NewLine}{Pipe}Diagnostic Report generated at: {DateTime.Now:dd-MM-yyyy HH:mm:ss.fff} in: {sw.Elapsed.TotalMilliseconds} milliseconds.{NewLine}"); - builder.Append('\\'); - return builder.ToString(); - } - - private static void AddSystem(StringBuilder builder) - { - var maxHeaderLength = SystemHeaders.Max(h => h.Length); - var formatter = "{0,-" + (maxHeaderLength + 1) + "}"; - - var sectionIndex = builder.Length; - Format(SystemHeaders[0], Environment.OSVersion); - Format(SystemHeaders[1], Environment.Is64BitOperatingSystem); - Format(SystemHeaders[2], Environment.Version); - Format(SystemHeaders[4], Environment.MachineName); - Format(SystemHeaders[3], NetworkHelper.GetFQDN()); - Format(SystemHeaders[8], Environment.UserDomainName + "\\" + Environment.UserName); - Format(SystemHeaders[6], GetProcessorName()); - Format(SystemHeaders[7], Environment.ProcessorCount); - Format(SystemHeaders[5], GetInstalledMemoryInGigaBytes()); - Format(SystemHeaders[9], Environment.SystemDirectory); - Format(SystemHeaders[10], Environment.CurrentDirectory); - - var maxLineLength = GetMaximumLineLength(builder, sectionIndex); - builder.Insert(sectionIndex, GetSeperator("System", maxLineLength)); - - void Format(string key, object value) - { - builder - .Append(LinePrefix) - .Append(Dot) - .Append(Space) - .AppendFormat(formatter, key) - .Append(Colon) - .Append(Space) - .AppendLine(value.ToString()); - } - } - - private static void AddDrives(StringBuilder builder) - { - var values = new List(); - - foreach (var d in DriveInfo.GetDrives()) - { - var row = new string[7]; - row[0] = d.Name; - row[1] = d.DriveType.ToString(); - - var dashString = Dash.ToString(); - string driveFormat = dashString, volumeLabel = dashString; - double capacity = 0, free = 0, available = 0; - - if (d.IsReady) - { - - driveFormat = d.DriveFormat; - volumeLabel = d.VolumeLabel; - capacity = d.TotalSize.Bytes().Gigabytes; - free = d.TotalFreeSpace.Bytes().Gigabytes; - available = d.AvailableFreeSpace.Bytes().Gigabytes; - } - - row[2] = driveFormat; - row[3] = volumeLabel; - row[4] = capacity.ToString("N0"); - row[5] = free.ToString("N0"); - row[6] = available.ToString("N0"); - - values.Add(row); - } - - WrapInTable(builder, DrivesHeaders, values); - } - - private static void AddNetworking(StringBuilder builder) - { - var result = ProcessHelper.ExecuteAsync("ipconfig", "/all").Result; - - var sectionIndex = builder.Length; - foreach (var entry in result.StandardOutput) - { - var entryLength = entry.Length; - if (entryLength == 0) { continue; } - - builder.Append(LinePrefix); - - var firstChar = entry[0]; - if (firstChar != Space) - { - // Add extra line between the new title and the previous - // lines only if it's not the first title - if (!entry.Equals("Windows IP Configuration", StringComparison.Ordinal)) - { - builder.AppendLine().Append(LinePrefix); - } - - if (entry[entryLength - 1] == Colon) { entryLength = entryLength - 1; } - - builder.Append(Dot).Append(Space); - for (var k = 0; k < entryLength; k++) { builder.Append(entry[k]); } - - builder.AppendLine().Append(LinePrefix); - - builder.Append(Space).Append(Space); - for (var j = 0; j < entryLength; j++) { builder.Append(Dash); } - } - else - { - builder.Append(Space).Append(Space); - - if (entryLength > 4) - { - if (entry[3] == Space) - { - builder.Append(Space).Append(Space); - } - else - { - builder.Append(Dot).Append(Space); - } - - for (var i = 3; i < entryLength; i++) - { - builder.Append(entry[i]); - } - - } - else - { - builder.Append("[Invalid Data]"); - } - } - - builder.AppendLine(); - } - - var maxLineLength = GetMaximumLineLength(builder, sectionIndex); - builder.Insert(sectionIndex, GetSeperator("Networking", maxLineLength)); - } - - private static void AddProcess(StringBuilder builder) - { - var maxHeaderLength = ProcessHeaders.Max(h => h.Length); - var formatter = "{0,-" + (maxHeaderLength + 1) + "}"; - - var sectionIndex = builder.Length; - using (var p = Process.GetCurrentProcess()) - { - var pVerInfo = p.MainModule.FileVersionInfo; - Format(ProcessHeaders[0], p.Id); - Format(ProcessHeaders[1], p.ProcessName); - Format(ProcessHeaders[2], p.StartTime.ToString("dd-MM-yyyy HH:mm:ss.fff")); - Format(ProcessHeaders[3], ApplicationHelper.GetProcessStartupDuration()); - Format(ProcessHeaders[17], Environment.UserInteractive); - Format(ProcessHeaders[4], IsOptimized()); - Format(ProcessHeaders[5], Environment.Is64BitProcess); - Format(ProcessHeaders[6], ApplicationHelper.IsProcessLargeAddressAware()); - Format(ProcessHeaders[16], Environment.WorkingSet.Bytes().Humanize()); - Format(ProcessHeaders[12], pVerInfo.FileVersion); - Format(ProcessHeaders[13], pVerInfo.ProductVersion); - Format(ProcessHeaders[14], pVerInfo.Language); - Format(ProcessHeaders[15], pVerInfo.LegalCopyright); - Format(ProcessHeaders[10], pVerInfo.OriginalFilename); - Format(ProcessHeaders[11], pVerInfo.FileName); - Format(ProcessHeaders[7], p.MainModule.ModuleName); - Format(ProcessHeaders[8], p.MainModule.FileName); - Format(ProcessHeaders[9], pVerInfo.ProductName); - - var cmdArgs = Environment.GetCommandLineArgs(); - Format(ProcessHeaders[18], cmdArgs[0]); - - for (var i = 1; i < cmdArgs.Length; i++) - { - builder - .Append(LinePrefix) - .Append(Space).Append(Space) - .AppendFormat(formatter, string.Empty) - .Append(Space).Append(Space) - .AppendLine(cmdArgs[i]); - } - - var maxLineLength = GetMaximumLineLength(builder, sectionIndex); - builder.Insert(sectionIndex, GetSeperator("Process", maxLineLength)); - - void Format(string key, object value) - { - builder - .Append(LinePrefix) - .Append(Dot) - .Append(Space) - .AppendFormat(formatter, key) - .Append(Colon) - .Append(Space) - .AppendLine(value.ToString()); - } - - string IsOptimized() - { - var executingAssembly = Assembly.GetEntryAssembly(); - return executingAssembly == null - ? "N/A - Assembly was called from Unmanaged code." - : executingAssembly.IsOptimized().ToString(); - } - } - } - - private static void AddAssemblies(StringBuilder builder) - { - var sectionIndex = builder.Length; - - var maxHeaderLength = AssemblyHeaders.Max(h => h.Length); - - var nameFormatter = "{0}{1:D3}{2} {3,-" + (maxHeaderLength + 1) + "}: {4}{5}"; - var formatter = "{0,-" + (maxHeaderLength + 1) + "}"; - - var assCounter = 1; - AppDomain.CurrentDomain.GetAssemblies() - .Where(ass => !ass.IsDynamic) - .OrderByDescending(o => o.GlobalAssemblyCache) - .ForEach(x => - { - builder.AppendFormat(nameFormatter, LinePrefix, assCounter, Pipe, AssemblyHeaders[0], x.FullName, NewLine); - - Format(AssemblyHeaders[1], x.GlobalAssemblyCache); - Format(AssemblyHeaders[2], !x.Is32Bit()); - Format(AssemblyHeaders[3], x.IsOptimized()); - Format(AssemblyHeaders[4], x.GetFrameworkVersion()); - Format(AssemblyHeaders[5], x.Location); - Format(AssemblyHeaders[6], x.CodeBase); - assCounter++; - }); - - var maxLineLength = GetMaximumLineLength(builder, sectionIndex); - builder.Insert(sectionIndex, GetSeperator("Assemblies", maxLineLength)); - - void Format(string key, object value) - { - builder - .Append(LinePrefix) - .Append(Space).Append(Space).Append(Space) - .Append(Dot) - .Append(Space) - .AppendFormat(formatter, key) - .Append(Colon) - .Append(Space) - .AppendLine(value.ToString()); - } - } - - private static void WrapInTable(StringBuilder builder, string[] columnHeaders, List values) - { - foreach (var row in values) - { - if (row.Length != columnHeaders.Length) - { - throw new InvalidDataException("There should be a corresponding data for every column header"); - } - } - - // initialize cellLengths first based on length of the headers - var cellLengths = new int[columnHeaders.Length]; - for (var i = 0; i < columnHeaders.Length; i++) - { - var headerLength = columnHeaders[i].Length; - cellLengths[i] = headerLength; - } - - foreach (var row in values) - { - for (var i = 0; i < columnHeaders.Length; i++) - { - var cellVal = row[i]; - if (cellVal.Length > cellLengths[i]) - { - cellLengths[i] = cellVal.Length; - } - } - } - - for (var i = 0; i < cellLengths.Length; i++) - { - cellLengths[i] = cellLengths[i] + 2; - } - - var headerBuilder = new StringBuilder(); - - // insert headers - headerBuilder.Append(LinePrefix); - for (var i = 0; i < columnHeaders.Length; i++) - { - var headerVal = columnHeaders[i]; - var formatter = "{0} {1,-" + (cellLengths[i] - 2) + "} "; - headerBuilder.AppendFormat(formatter, Pipe, headerVal); - } - headerBuilder.Append(Pipe).AppendLine(); - - // insert headers underline - headerBuilder.Append(LinePrefix); - for (var i = 0; i < columnHeaders.Length; i++) - { - headerBuilder.Append(Pipe).Append(new string(Dash, cellLengths[i])); - } - - var maxLineLengthInHeader = GetMaximumLineLength(headerBuilder); - var beginAndEnd = $"{LinePrefix} {new string(Dash, maxLineLengthInHeader - LinePrefix.Length - 2)}{NewLine}"; - headerBuilder.Insert(0, beginAndEnd); - - var beginPos = builder.Length; - - // insert row values - builder.Append(Pipe).AppendLine(); - foreach (var row in values) - { - builder.Append(LinePrefix); - for (var j = 0; j < row.Length; j++) - { - var formatter = "{0} {1,-" + (cellLengths[j] - 2) + "} "; - builder.AppendFormat(formatter, Pipe, row[j]); - } - builder.Append(Pipe).AppendLine(); - } - - builder.Insert(beginPos, headerBuilder.ToString()); - builder.Append(beginAndEnd); - - var maxLineLength = GetMaximumLineLength(builder, beginPos); - builder.Insert(beginPos, GetSeperator("Drives", maxLineLength)); - } - - private static int GetMaximumLineLength(StringBuilder builder, int start = 0) - { - if (start >= builder.Length) { throw new IndexOutOfRangeException(); } - - int maxLength = 0, tmpLength = 0; - var prevChar = '\0'; - - for (var i = start; i < builder.Length; i++) - { - var currChar = builder[i]; - - if (currChar == '\n') - { - if (prevChar == '\r') { --tmpLength; } - if (maxLength < tmpLength) { maxLength = tmpLength; } - tmpLength = 0; - } - else { tmpLength++; } - - prevChar = currChar; - } - return maxLength; - } - - /// - /// Returns the full CPU name using the registry. - /// See - /// - /// The CPU Name - private static string GetProcessorName() - { - var key = Registry.LocalMachine.OpenSubKey(@"HARDWARE\DESCRIPTION\System\CentralProcessor\0\"); - return key?.GetValue("ProcessorNameString").ToString() ?? "Not Found"; - } - - private static string GetInstalledMemoryInGigaBytes() - { - GetPhysicallyInstalledSystemMemory(out var installedMemoryKb); - return installedMemoryKb.Bytes().Humanize(); - } - - private static string GetSeperator(string title, int count) - { - return $"{Pipe}{NewLine}{Pipe}{title}{Pipe}{new string(Dot, count - title.Length)}{NewLine}{Pipe}{NewLine}"; - } - - /// - /// - /// - [DllImport("kernel32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool GetPhysicallyInstalledSystemMemory(out long totalMemoryInKilobytes); - } -} diff --git a/src/Maple.Core/DiagnosticReportType.cs b/src/Maple.Core/DiagnosticReportType.cs deleted file mode 100644 index 7537fd2..0000000 --- a/src/Maple.Core/DiagnosticReportType.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; - -namespace Maple.Core -{ - /// - /// Represents the different types of report which can - /// be generated by . - /// - /// Reports can be mixed as: - /// - /// DiagnosticReportType.System | DiagnosticReportType.Process - /// - /// - /// - [Flags] - public enum DiagnosticReportType - { - /// - /// Includes details about the System. - /// - System = 1, - - /// - /// Includes details about the Process. - /// - Process = 2, - - /// - /// Includes details about the Drives. - /// - Drives = 4, - - /// - /// Includes details about the referenced Assemblies. - /// - Assemblies = 8, - - /// - /// Includes details about the Networking. - /// - Networking = 16, - - /// - /// Generates the full report. - /// - Full = System | Process | Drives | Assemblies | Networking - } -} diff --git a/src/Maple.Core/DispatcherFactory.cs b/src/Maple.Core/DispatcherFactory.cs deleted file mode 100644 index 792347d..0000000 --- a/src/Maple.Core/DispatcherFactory.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Windows.Threading; - -namespace Maple.Core -{ - public static class DispatcherFactory - { - /// - /// Gets the dispatcher. - /// - /// - public static Dispatcher GetDispatcher() - { - return Dispatcher.CurrentDispatcher; - } - - /// - /// Invokes the specified action. - /// - /// The action. - public static void Invoke(Action action) - { - var dispatcher = GetDispatcher(); - - if (dispatcher.CheckAccess()) - action(); - else - dispatcher.BeginInvoke(action); - } - - /// - /// Invokes the specified action. - /// - /// - /// The action. - /// The parameter. - /// The priority. - public static void Invoke(Action action, T parameter, DispatcherPriority priority = DispatcherPriority.Normal) - { - var dispatcher = GetDispatcher(); - - if (dispatcher.CheckAccess()) - action?.Invoke(parameter); - else - dispatcher.BeginInvoke(action, priority, parameter); - } - } -} diff --git a/src/Maple.Core/DynamicDictionary.cs b/src/Maple.Core/DynamicDictionary.cs deleted file mode 100644 index 471ce19..0000000 --- a/src/Maple.Core/DynamicDictionary.cs +++ /dev/null @@ -1,219 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Dynamic; - -namespace Maple.Core -{ - /// - /// Provides an abstraction for an object to be used dynamically as a key value pair - /// where the property is the key and value is an . - /// - public sealed class DynamicDictionary : DynamicObject, IDictionary - { - private readonly IDictionary _dictionary; - - /// - /// Creates a new instance of . - /// - /// - /// The flag indicating whether keys should be treated regardless of the case. - /// - [DebuggerStepThrough] - public DynamicDictionary(bool ignoreCase = true) - { - _dictionary = new Dictionary( - ignoreCase ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal); - } - - /// - /// Add the given to this instance. - /// - /// - public void Add(KeyValuePair item) - { - _dictionary.Add(item); - } - - /// - /// Removes all the items from this instance. - /// - public void Clear() - { - _dictionary.Clear(); - } - - /// - /// Determines whether this instance contains the given . - /// - public bool Contains(KeyValuePair item) - { - return _dictionary.Contains(item); - } - - /// - /// Copies the elements of this instance to the given , starting at a particular . - /// - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - _dictionary.CopyTo(array, arrayIndex); - } - - /// - /// Removes the given from this instance. - /// - public bool Remove(KeyValuePair item) - { - return _dictionary.Remove(item); - } - - /// - /// Gets the number of elements contained in this instance. - /// - public int Count => _dictionary.Keys.Count; - - /// - /// Determines whether this instance is Read-Only. - /// - public bool IsReadOnly => _dictionary.IsReadOnly; - - /// - /// Returns an enumerator that iterates through the keys and values of this instance. - /// - public IEnumerator> GetEnumerator() - { - return _dictionary.GetEnumerator(); - } - - /// - /// Returns an enumerator that iterates through the keys and values of this instance. - /// - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - /// - /// Determines whether this instance contains an element with the given . - /// - public bool ContainsKey(string key) - { - return _dictionary.ContainsKey(key); - } - - /// - /// Adds an element for the given and associated to this instance. - /// - public void Add(string key, object value) - { - _dictionary.Add(key, value); - } - - /// - /// Removes the element with the given from this instance. - /// - public bool Remove(string key) - { - return _dictionary.Remove(key); - } - - /// - /// Attempts to get the value associated to the given . - /// - public bool TryGetValue(string key, out object value) - { - return _dictionary.TryGetValue(key, out value); - } - - /// - /// Gets or sets the value stored against the given . - /// If the given does not exist, NULL is returned. - /// - public object this[string key] - { - get - { - _dictionary.TryGetValue(key, out var result); - return result; - } - - set { _dictionary[key] = value; } - } - - /// - /// Gets an containing the keys of this instance. - /// - public ICollection Keys => _dictionary.Keys; - - /// - /// Gets an containing the values of this instance. - /// - public ICollection Values => _dictionary.Values; - - /// - /// Attempts to get the member. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool TryGetMember(GetMemberBinder binder, out object result) - { - if (_dictionary.ContainsKey(binder.Name)) - { - result = _dictionary[binder.Name]; - return true; - } - - if (base.TryGetMember(binder, out result)) - { - return true; - } - - // always return null if not found. - result = null; - return true; - } - - /// - /// Attempts to set the member. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool TrySetMember(SetMemberBinder binder, object result) - { - if (!_dictionary.ContainsKey(binder.Name)) { _dictionary.Add(binder.Name, result); } - else { _dictionary[binder.Name] = result; } - return true; - } - - /// - /// Attempts to invoke the member. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) - { - if (_dictionary.ContainsKey(binder.Name) && _dictionary[binder.Name] is Delegate) - { - var del = (Delegate)_dictionary[binder.Name]; - result = del.DynamicInvoke(args); - return true; - } - - return base.TryInvokeMember(binder, args, out result); - } - - /// - /// Attempts to delete the member. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool TryDeleteMember(DeleteMemberBinder binder) - { - if (_dictionary.ContainsKey(binder.Name)) - { - _dictionary.Remove(binder.Name); - return true; - } - - return base.TryDeleteMember(binder); - } - } -} diff --git a/src/Maple.Core/Ensure.cs b/src/Maple.Core/Ensure.cs index 84c7945..9d279e8 100644 --- a/src/Maple.Core/Ensure.cs +++ b/src/Maple.Core/Ensure.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.IO; using System.Linq; + using Maple.Localization.Properties; namespace Maple.Core @@ -22,7 +23,7 @@ public static class Ensure /// Thrown when TException is . /// [DebuggerStepThrough] - public static void That(bool condition, string message = default(string)) + public static void That(bool condition, string message = default) where TException : Exception { if (!condition) @@ -43,7 +44,7 @@ public static class Ensure /// Thrown when is . /// [DebuggerStepThrough] - public static void That(bool condition, string message = default(string)) + public static void That(bool condition, string message = default) { if (string.IsNullOrEmpty(message)) message = Resources.ExceptionMessageFalseCondition; @@ -61,7 +62,7 @@ public static class Ensure /// Thrown when is . /// [DebuggerStepThrough] - public static void Not(bool condition, string message = default(string)) + public static void Not(bool condition, string message = default) where TException : Exception { if (string.IsNullOrEmpty(message)) @@ -79,7 +80,7 @@ public static class Ensure /// Thrown when is . /// [DebuggerStepThrough] - public static void Not(bool condition, string message = default(string)) + public static void Not(bool condition, string message = default) { if (string.IsNullOrEmpty(message)) message = Resources.ExceptionMessageFalseCondition; @@ -122,7 +123,7 @@ public static T NotNull(T value, string argName) /// /// Null values will cause an exception to be thrown [DebuggerStepThrough] - public static void Equal(T left, T right, string message = default(string)) + public static void Equal(T left, T right, string message = default) { if (string.IsNullOrEmpty(message)) message = Resources.ExceptionMessageEqualValues; @@ -142,7 +143,7 @@ public static T NotNull(T value, string argName) /// /// Null values will cause an exception to be thrown [DebuggerStepThrough] - public static void NotEqual(T left, T right, string message = default(string)) + public static void NotEqual(T left, T right, string message = default) { if (string.IsNullOrEmpty(message)) message = Resources.ExceptionMessageNotEqualValues; @@ -164,7 +165,7 @@ public static T NotNull(T value, string argName) /// Thrown when is empty. /// [DebuggerStepThrough] - public static ICollection NotNullOrEmpty(ICollection collection, string message = default(string)) + public static ICollection NotNullOrEmpty(ICollection collection, string message = default) { if (string.IsNullOrEmpty(message)) message = Resources.ExceptionMessageCollectionNullOrEmpty; @@ -184,7 +185,7 @@ public static T NotNull(T value, string argName) /// Thrown when is null or empty or whitespace. /// [DebuggerStepThrough] - public static string NotNullOrEmptyOrWhiteSpace(string value, string message = default(string)) + public static string NotNullOrEmptyOrWhiteSpace(string value, string message = default) { if (string.IsNullOrEmpty(message)) message = Resources.ExceptionMessageStringNullEmpyOrWhiteSpace; diff --git a/src/Maple.Core/Extensions/GenericExtensions.cs b/src/Maple.Core/Extensions/GenericExtensions.cs deleted file mode 100644 index 43efc07..0000000 --- a/src/Maple.Core/Extensions/GenericExtensions.cs +++ /dev/null @@ -1,241 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Dynamic; -using System.Linq; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.Serialization; - -namespace Maple.Core -{ - /// - /// A set of extension methods for generic types. - /// - public static class GenericExtensions - { - /// - /// This dictionary caches the delegates for each 'to-clone' type. - /// - private static readonly Dictionary CachedIlShallow = new Dictionary(); - private static readonly Dictionary CachedIlDeep = new Dictionary(); - private static LocalBuilder _localBuilder; - - /// - /// Converts the given to a . - /// - public static DynamicDictionary ToDynamic(this T @object, bool inherit = true) - { - var dynDic = new DynamicDictionary(); - foreach (var property in @object.GetType().GetInstanceProperties(inherit)) - { - dynDic.Add(property.Name, property.GetValue(@object, null)); - } - - return dynDic; - } - - /// - /// Returns True if has the default value of . - /// - /// The object to check for default. - /// True if has default or null value otherwise False. - public static bool IsDefault(this T @object) - { - return EqualityComparer.Default.Equals(@object, default(T)); - } - - /// - /// Returns an uninitialized instance of the without calling any of its constructor(s). - /// - /// - /// - /// Because the new instance of the object is initialized to zero and no constructors are run, - /// the object might not represent a state that is regarded as valid by that object. - /// The current method should only be used for deserialization when the user intends to immediately - /// populate all fields. It does not create an uninitialized string, - /// since creating an empty instance of an immutable type serves no purpose. - /// - /// Generic Type - /// An instance of type - /// with all its non-static fields initialized to its default value. - /// - public static T GetUninitializedInstance() - { - return (T)FormatterServices.GetUninitializedObject(typeof(T)); - } - - /// - /// Gets all the private, public, inherited instance property names for the given . - /// - /// This method can be used to return both a public or non-public property names - /// and supports instances of . - /// - /// Object to get properties from - /// The flag indicating whether inherited properties should be included or not - /// The flag indicating whether private properties should be included or not - /// - public static string[] GetPropertyNames(this T @object, bool inherit = true, bool includePrivate = true) - { - if (@object is IDynamicMetaObjectProvider expando) - { - var dic = (IDictionary)expando; - return dic.Keys.ToArray(); - } - - return @object.GetType() - .GetInstanceProperties(inherit, includePrivate) - .Select(p => p.Name).ToArray(); - } - - /// - /// Generic cloning method that clones an object using IL. - /// Only the first call of a certain type will hold back performance. - /// After the first call, the compiled IL is executed. - /// - /// Type of object to clone - /// Object to clone - /// Cloned object - public static T CloneShallowUsingIl(this T @object) - { - var type = typeof(T); - if (!CachedIlShallow.TryGetValue(type, out var myExec)) - { - // Create ILGenerator (both DM declarations work) - var dymMethod = new DynamicMethod("DoClone", type, new[] { type }, Assembly.GetExecutingAssembly().ManifestModule, true); - var cInfo = @object.GetType().GetConstructor(new Type[] { }); - var generator = dymMethod.GetILGenerator(); - - generator.Emit(OpCodes.Newobj, cInfo); - generator.Emit(OpCodes.Stloc_0); - foreach (var field in @object.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) - { - generator.Emit(OpCodes.Ldloc_0); - generator.Emit(OpCodes.Ldarg_0); - generator.Emit(OpCodes.Ldfld, field); - generator.Emit(OpCodes.Stfld, field); - } - generator.Emit(OpCodes.Ldloc_0); - generator.Emit(OpCodes.Ret); - myExec = dymMethod.CreateDelegate(typeof(Func)); - CachedIlShallow.Add(type, myExec); - } - return ((Func)myExec)(@object); - } - - /// - /// Performs a deep copy of the object using the by generating IL. - /// Only the first call for a certain type will have impact on performance; After the first call, the compiled IL is executed. - /// - /// - /// The type of object being cloned. - /// The object instance to clone. - /// the cloned object - public static T CloneDeepUsingIl(this T myObject) - { - var type = typeof(T); - if (!CachedIlDeep.TryGetValue(type, out var myExec)) - { - // Create ILGenerator (both DM declarations work) - var dymMethod = new DynamicMethod("DoClone", type, new[] { type }, Assembly.GetExecutingAssembly().ManifestModule, true); - var cInfo = myObject.GetType().GetConstructor(new Type[] { }); - var generator = dymMethod.GetILGenerator(); - - generator.Emit(OpCodes.Newobj, cInfo); - generator.Emit(OpCodes.Stloc_0); - - foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) - { - if (field.FieldType.IsValueType || field.FieldType == typeof(string)) - { - CopyValueType(generator, field); - } - else if (field.FieldType.IsClass) - { - CopyReferenceType(generator, field); - } - } - generator.Emit(OpCodes.Ldloc_0); - generator.Emit(OpCodes.Ret); - myExec = dymMethod.CreateDelegate(typeof(Func)); - CachedIlDeep.Add(type, myExec); - } - return ((Func)myExec)(myObject); - } - - private static void CopyValueType(ILGenerator generator, FieldInfo field) - { - generator.Emit(OpCodes.Ldloc_0); - generator.Emit(OpCodes.Ldarg_0); - generator.Emit(OpCodes.Ldfld, field); - generator.Emit(OpCodes.Stfld, field); - } - - private static void CopyReferenceType(ILGenerator generator, FieldInfo field) - { - // We have a reference type. - _localBuilder = generator.DeclareLocal(field.FieldType); - if (field.FieldType.GetInterface("IEnumerable") != null) - { - // We have a list type (generic). - if (field.FieldType.IsGenericType) - { - // Get argument of list type - var argType = field.FieldType.GetGenericArguments()[0]; - // Check that it has a constructor that accepts another IEnumerable. - var genericType = typeof(IEnumerable<>).MakeGenericType(argType); - - var ci = field.FieldType.GetConstructor(new[] { genericType }); - if (ci != null) - { - // It has! (Like the List<> class) - generator.Emit(OpCodes.Ldarg_0); - generator.Emit(OpCodes.Ldfld, field); - generator.Emit(OpCodes.Newobj, ci); - generator.Emit(OpCodes.Stloc, _localBuilder); - PlaceNewTempObjInClone(generator, field); - } - } - } - else - { - CreateNewTempObject(generator, field.FieldType); - PlaceNewTempObjInClone(generator, field); - foreach (var fi in field.FieldType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) - { - if (fi.FieldType.IsValueType || fi.FieldType == typeof(string)) - { - CopyValueTypeTemp(generator, field, fi); - } - else if (fi.FieldType.IsClass) - { - CopyReferenceType(generator, fi); - } - } - } - } - - private static void CreateNewTempObject(ILGenerator generator, Type type) - { - var cInfo = type.GetConstructor(new Type[] { }); - generator.Emit(OpCodes.Newobj, cInfo); - generator.Emit(OpCodes.Stloc, _localBuilder); - } - - private static void PlaceNewTempObjInClone(ILGenerator generator, FieldInfo field) - { - // Get object from custom location and store it in right field of location 0 - generator.Emit(OpCodes.Ldloc_0); - generator.Emit(OpCodes.Ldloc, _localBuilder); - generator.Emit(OpCodes.Stfld, field); - } - - private static void CopyValueTypeTemp(ILGenerator generator, FieldInfo fieldParent, FieldInfo fieldDetail) - { - generator.Emit(OpCodes.Ldloc_1); - generator.Emit(OpCodes.Ldarg_0); - generator.Emit(OpCodes.Ldfld, fieldParent); - generator.Emit(OpCodes.Ldfld, fieldDetail); - generator.Emit(OpCodes.Stfld, fieldDetail); - } - } -} diff --git a/src/Maple.Core/Extensions/LinqExtensions.cs b/src/Maple.Core/Extensions/LinqExtensions.cs index d171958..7a7a3ba 100644 --- a/src/Maple.Core/Extensions/LinqExtensions.cs +++ b/src/Maple.Core/Extensions/LinqExtensions.cs @@ -26,7 +26,7 @@ public static T Random(this IEnumerable baseCollection) // consider a thread-safe static instance var r = new Random(); var list = baseCollection as IList ?? baseCollection.ToList(); - return list.Count == 0 ? default(T) : list[r.Next(0, list.Count)]; + return list.Count == 0 ? default : list[r.Next(0, list.Count)]; } public static IEnumerable ForEach(this IEnumerable baseCollection, Func action) diff --git a/src/Maple.Core/Extensions/StringExtensions.cs b/src/Maple.Core/Extensions/StringExtensions.cs index 67332a0..492b076 100644 --- a/src/Maple.Core/Extensions/StringExtensions.cs +++ b/src/Maple.Core/Extensions/StringExtensions.cs @@ -1,15 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using System.Xml; -using System.Xml.Linq; +using System.Diagnostics; namespace Maple.Core { @@ -19,40 +8,24 @@ namespace Maple.Core public static class StringExtensions { /// - /// Contains characters that may be used as regular expression arguments after \. - /// - private static readonly char[] RegexCharacters = { 'G', 'Z', 'A', 'n', 'W', 'w', 'v', 't', 's', 'S', 'r', 'k', 'f', 'D', 'd', 'B', 'b' }; - - private static readonly char[] InvalidFileNameCharacters = Path.GetInvalidFileNameChars(); - private static readonly char[] InvalidPathCharacters = Path.GetInvalidPathChars(); - /// - /// A nicer way of calling - /// - /// The string to test. - /// if the format parameter is null or an empty string (""); otherwise, . + /// A nicer way of calling The string to test. if the format + /// parameter is null or an empty string (""); otherwise, . [DebuggerStepThrough] public static bool IsNullOrEmpty(this string value) { return string.IsNullOrEmpty(value); } - /// - /// A nice way of calling the inverse of - /// - /// The string to test. - /// if the format parameter is not null or an empty string (""); otherwise, . - [DebuggerStepThrough] - public static bool IsNotNullOrEmpty(this string value) - { - return !value.IsNullOrEmpty(); - } - /// /// A nice way of checking if a string is null, empty or whitespace /// /// The string to test. - /// if the format parameter is null or an empty string (""); otherwise, . + /// + /// if the format parameter is null or an empty string (""); otherwise, + /// . + /// [DebuggerStepThrough] public static bool IsNullOrEmptyOrWhiteSpace(this string value) { @@ -63,613 +36,14 @@ public static bool IsNullOrEmptyOrWhiteSpace(this string value) /// A nice way of checking the inverse of (if a string is null, empty or whitespace) /// /// The string to test. - /// if the format parameter is not null or an empty string (""); otherwise, . - [DebuggerStepThrough] - public static bool IsNotNullOrEmptyOrWhiteSpace(this string value) - { - return !value.IsNullOrEmptyOrWhiteSpace(); - } - - /// - /// Parses a string as Boolean, valid inputs are: true|false|yes|no|1|0. - /// Input is parsed as Case-Insensitive. - /// - public static bool TryParseAsBool(this string value, out bool result) - { - Ensure.NotNull(value, nameof(value)); - - const StringComparison CompPolicy = StringComparison.OrdinalIgnoreCase; - - if (value.Equals("true", CompPolicy) - || value.Equals("yes", CompPolicy) - || value.Equals("1", CompPolicy)) - { - result = true; - return true; - } - - if (value.Equals("false", CompPolicy) - || value.Equals("no", CompPolicy) - || value.Equals("0", CompPolicy)) - { - result = false; - return true; - } - - result = false; - return false; - } - - /// Formats arguments into string based on the provided . - /// The as string. - /// The arguments. - /// The formatted string. - /// Thrown when is null or empty or whitespace. - [DebuggerStepThrough] - public static string FormatWith(this string format, params object[] args) - { - Ensure.NotNullOrEmptyOrWhiteSpace(format); - return string.Format(format, args); - } - - /// Formats arguments into string based on the provided . - /// The as string. - /// The format provider. - /// The arguments. - /// The formatted string. - /// Thrown when is null or empty or whitespace. - [DebuggerStepThrough] - public static string FormatWith(this string format, IFormatProvider provider, params object[] args) - { - Ensure.NotNullOrEmptyOrWhiteSpace(format); - return string.Format(provider, format, args); - } - - /// - /// Allows for using strings in coalescing operations. - /// - /// The string value to check. - /// Null if is empty or the original . - [DebuggerStepThrough] - public static string NullIfEmpty(this string value) - { - return value == string.Empty ? null : value; - } - - /// - /// Tries to extract the value between the tag from the . - /// This method is case insensitive. - /// - /// The input string. - /// The tag whose value will be returned e.g span, img. - /// The extracted value. - /// True if successful otherwise False. - public static bool TryExtractValueFromTag(this string input, string tagName, out string value) - { - Ensure.NotNull(input, nameof(input)); - Ensure.NotNull(tagName, nameof(tagName)); - - var pattern = $"<{tagName}[^>]*>(.*)"; - var match = Regex.Match(input, pattern, RegexOptions.IgnoreCase); - - if (match.Success) - { - value = match.Groups[1].ToString(); - return true; - } - - value = null; - return false; - } - - /// - /// Returns a string array containing the trimmed substrings in this - /// that are delimited by the provided . - /// - public static string[] SplitAndTrim(this string value, params char[] separators) - { - Ensure.NotNull(value, nameof(value)); - return value.Trim() - .Split(separators, StringSplitOptions.RemoveEmptyEntries) - .Select(s => s.Trim()) - .ToArray(); - } - - /// - /// Checks if the contains the based on the provided rules. - /// - public static bool Contains(this string input, string stringToCheckFor, StringComparison comparison) - { - return input.IndexOf(stringToCheckFor, comparison) >= 0; - } - - /// - /// Checks that given matches any of the potential matches. - /// Inspired by: http://stackoverflow.com/a/20644611/23199 - /// - public static bool EqualsAny(this string input, StringComparer comparer, string match1, string match2) - { - return comparer.Equals(input, match1) || comparer.Equals(input, match2); - } - - /// - /// Checks that given matches any of the potential matches. - /// Inspired by: http://stackoverflow.com/a/20644611/23199 - /// - public static bool EqualsAny(this string input, StringComparer comparer, string match1, string match2, string match3) - { - return comparer.Equals(input, match1) || comparer.Equals(input, match2) || comparer.Equals(input, match3); - } - - /// - /// Checks that given is in a list of potential . - /// Inspired by: http://stackoverflow.com/a/20644611/23199 - /// - public static bool EqualsAny(this string input, StringComparer comparer, params string[] matches) - { - return matches.Any(x => comparer.Equals(x, input)); - } - - /// - /// Checks to see if the given input is a valid palindrome or not. - /// - /// The input string - /// True if palindrome otherwise False - public static bool IsPalindrome(this string input) - { - Ensure.NotNull(input, nameof(input)); - var min = 0; - var max = input.Length - 1; - while (true) - { - if (min > max) { return true; } - - var a = input[min]; - var b = input[max]; - if (char.ToLower(a) != char.ToLower(b)) { return false; } - - min++; - max--; - } - } - - /// - /// Truncates the to the maximum length of and - /// replaces the truncated part with - /// - /// The input string - /// Total length of characters to maintain before truncation. - /// The suffix to add to the end of the truncated - /// Truncated string. - public static string Truncate(this string input, int maxLength, string suffix = "") - { - Ensure.NotNull(input, nameof(input)); - Ensure.NotNull(suffix, nameof(suffix)); - - if (maxLength < 0) { return input; } - if (maxLength == 0) { return string.Empty; } - - var chars = input.Take(maxLength).ToArray(); - - if (chars.Length != input.Length) - { - return new string(chars) + suffix; - } - - return new string(chars); - } - - /// - /// Removes different types of new lines from a given string. - /// - /// input string. - /// The given input minus any new line characters. - public static string RemoveNewLines(this string input) - { - Ensure.NotNull(input, nameof(input)); - return input.Replace("\n", string.Empty).Replace("\r", string.Empty); - } - - /// - /// Separates a PascalCase string. - /// - /// "ThisIsPascalCase".SeparatePascalCase(); // returns "This Is Pascal Case" - /// The format to split - /// The original string separated on each uppercase character. - public static string SeparatePascalCase(this string value) - { - Ensure.NotNullOrEmptyOrWhiteSpace(value); - return Regex.Replace(value, "([A-Z])", " $1").Trim(); - } - - /// - /// Converts string to Pascal Case - /// This Is A Pascal Case String. - /// - /// The given input. - /// The given converted to Pascal Case. - public static string ToPascalCase(this string input) - { - Ensure.NotNull(input, nameof(input)); - - var cultureInfo = Thread.CurrentThread.CurrentCulture; - var textInfo = cultureInfo.TextInfo; - return textInfo.ToTitleCase(input); - } - - /// - /// Compares against , the comparison is case-sensitive. - /// - /// The input string - /// The target string - /// True if equal otherwise False - public static bool IsEqualTo(this string input, string target) - { - if (input == null && target == null) { return true; } - if (input == null || target == null) { return false; } - if (input.Length != target.Length) { return false; } - - return string.CompareOrdinal(input, target) == 0; - } - - /// - /// Handy method to print arguments to System.Console. - /// - /// The input string. - /// The arguments. - [DebuggerStepThrough] - public static void Print(this string input, params object[] args) - { - Console.WriteLine(input, args); - } - - /// - /// Generates a slug. - /// - /// Credit goes to . - /// - /// - [DebuggerStepThrough] - public static string GenerateSlug(this string value, uint? maxLength = null) - { - // prepare string, remove diacritics, lower case and convert hyphens to whitespace - var result = RemoveDiacritics(value).Replace("-", " ").ToLowerInvariant(); - - result = Regex.Replace(result, @"[^a-z0-9\s-]", string.Empty); // remove invalid characters - result = Regex.Replace(result, @"\s+", " ").Trim(); // convert multiple spaces into one space - - if (maxLength.HasValue) - { - result = result.Substring(0, result.Length <= maxLength ? result.Length : (int)maxLength.Value).Trim(); - } - return Regex.Replace(result, @"\s", "-"); - } - - /// - /// Removes the diacritics from the given - /// - /// - /// Credit goes to . - /// - [DebuggerStepThrough] - public static string RemoveDiacritics(this string input) - { - var normalizedString = input.Normalize(NormalizationForm.FormD); - var stringBuilder = StringBuilderCache.Acquire(); - - foreach (var c in normalizedString) - { - var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c); - if (unicodeCategory != UnicodeCategory.NonSpacingMark) - { - stringBuilder.Append(c); - } - } - - return StringBuilderCache.GetStringAndRelease(stringBuilder).Normalize(NormalizationForm.FormC); - } - - /// - /// A method to convert English digits to Persian numbers. - /// - public static string ToPersianNumber(this string input) - { - Ensure.NotNull(input, nameof(input)); - return input - .Replace("0", "۰") - .Replace("1", "۱") - .Replace("2", "۲") - .Replace("3", "۳") - .Replace("4", "۴") - .Replace("5", "۵") - .Replace("6", "۶") - .Replace("7", "۷") - .Replace("8", "۸") - .Replace("9", "۹"); - } - - /// - /// Gets a sequence containing every element with the name equal to . - /// - /// The input containing XML - /// The name of the elements to return - /// The flag indicating whether the name should be looked up in a case sensitive manner - /// The sequence containing all the elements matching the - public static IEnumerable GetElements(this string xmlInput, XName name, bool ignoreCase = true) - { - Ensure.NotNull(xmlInput, nameof(xmlInput)); - return xmlInput.GetElements(name, new XmlReaderSettings(), ignoreCase); - } - - /// - /// Gets a sequence containing every element with the name equal to . - /// - /// The input containing XML - /// The name of the elements to return - /// The settings used by the - /// The flag indicating whether the name should be looked up in a case sensitive manner - /// The sequence containing all the elements matching the - public static IEnumerable GetElements(this string xmlInput, XName name, XmlReaderSettings settings, bool ignoreCase = true) - { - Ensure.NotNull(xmlInput, nameof(xmlInput)); - Ensure.NotNull(name, nameof(name)); - Ensure.NotNull(settings, nameof(settings)); - - using (var stringReader = new StringReader(xmlInput)) - using (var xmlReader = XmlReader.Create(stringReader, settings)) - { - foreach (var xElement in xmlReader.GetEelements(name, ignoreCase)) - { - yield return xElement; - } - } - } - - /// - /// Compresses the given to Base64 string. - /// - /// The string to be compressed - /// The compressed string in Base64 - public static string Compress(this string input) - { - Ensure.NotNull(input, nameof(input)); - - var buffer = Encoding.UTF8.GetBytes(input); - using (var memStream = new MemoryStream()) - using (var zipStream = new GZipStream(memStream, CompressionMode.Compress, true)) - { - zipStream.Write(buffer, 0, buffer.Length); - zipStream.Close(); - - memStream.Position = 0; - - var compressedData = new byte[memStream.Length]; - memStream.Read(compressedData, 0, compressedData.Length); - - var gZipBuffer = new byte[compressedData.Length + 4]; - Buffer.BlockCopy(compressedData, 0, gZipBuffer, 4, compressedData.Length); - Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gZipBuffer, 0, 4); - return Convert.ToBase64String(gZipBuffer); - } - } - - /// - /// Decompresses a Base64 compressed string. - /// - /// The string compressed in Base64 - /// The uncompressed string - public static string Decompress(this string compressedInput) - { - Ensure.NotNull(compressedInput, nameof(compressedInput)); - - var gZipBuffer = Convert.FromBase64String(compressedInput); - using (var memStream = new MemoryStream()) - { - var dataLength = BitConverter.ToInt32(gZipBuffer, 0); - memStream.Write(gZipBuffer, 4, gZipBuffer.Length - 4); - memStream.Position = 0; - - var buffer = new byte[dataLength]; - using (var zipStream = new GZipStream(memStream, CompressionMode.Decompress)) - { - zipStream.Read(buffer, 0, buffer.Length); - } - - return Encoding.UTF8.GetString(buffer); - } - } - - /// - /// Ensures the given can be used as a file name. - /// - public static bool IsValidFileName(this string input) - { - return input.IsNotNullOrEmptyOrWhiteSpace() && input.IndexOfAny(InvalidFileNameCharacters) == -1; - } - - /// - /// Ensures the given can be used as a path. - /// - public static bool IsValidPathName(this string input) - { - return input.IsNotNullOrEmptyOrWhiteSpace() && input.IndexOfAny(InvalidPathCharacters) == -1; - } - - /// - /// Returns a from a Base64 encoded . - /// - /// DRfscsSQbUu8bXRqAvcWQA== or DRfscsSQbUu8bXRqAvcWQA depending on . - /// - /// - /// See: - /// - /// - public static Guid ToGuid(this string input, bool trimmed = true) - { - return trimmed ? new Guid(Convert.FromBase64String(input + "==")) - : new Guid(Convert.FromBase64String(input)); - } - - /// - /// Converts API to [aA][pP][iI]. - /// - /// This should be used as much faster alternative to adding - /// or using the (?i) for example (?i)API(?-i) - /// - /// - public static string ToCaseIncensitiveRegexArgument(this string input) - { - if (input.IsNullOrEmptyOrWhiteSpace()) { return input; } - - var patternIndexes = input.GetStartAndEndIndexes("(?<", ">").ToArray(); - var hasPattern = patternIndexes.Length > 0; - var isInPattern = false; - - var builder = StringBuilderCache.Acquire(); - // ReSharper disable once ForCanBeConvertedToForeach - for (var i = 0; i < input.Length; i++) - { - var prev = i == 0 ? new char() : input[i - 1]; - var currChar = input[i]; - - if (hasPattern) - { - foreach (var pair in patternIndexes) - { - if (i >= pair.Key && i <= pair.Value) - { - isInPattern = true; - break; - } - - isInPattern = false; - } - } - - if (!char.IsLetter(currChar) - || (prev == '\\' && RegexCharacters.Contains(currChar)) - || isInPattern) - { - builder.Append(currChar); - continue; - } - - builder.Append('['); - - if (char.IsUpper(currChar)) - { - builder.Append(char.ToLower(currChar)).Append(currChar); - } - else - { - builder.Append(currChar).Append(char.ToUpper(currChar)); - } - builder.Append(']'); - } - return StringBuilderCache.GetStringAndRelease(builder); - } - - /// - /// Returns all the start and end indexes of the occurrences of the - /// given and - /// in the given . - /// - /// The input to search. - /// The starting tag e.g. <div>. - /// The ending tag e.g. </div>. /// - /// A sequence where the key is - /// the starting position and value is the end position. + /// if the format parameter is not null or an empty string (""); + /// otherwise, . /// [DebuggerStepThrough] - public static IEnumerable> GetStartAndEndIndexes(this string input, string startTag, string endTag) - { - var startIdx = 0; - int endIdx; - - while ((startIdx = input.IndexOf(startTag, startIdx, StringComparison.Ordinal)) != -1 - && (endIdx = input.IndexOf(endTag, startIdx, StringComparison.Ordinal)) != -1) - { - var result = new KeyValuePair(startIdx, endIdx); - startIdx = endIdx; - yield return result; - } - } - } - - /// - /// Extension methods for classes in the namespace. - /// - public static class XmlExtensions - { - /// - /// Sets the default XML namespace of every element in the given XML element - /// - public static void SetDefaultXmlNamespace(this XElement element, XNamespace xmlns) - { - Ensure.NotNull(element, nameof(element)); - Ensure.NotNull(xmlns, nameof(xmlns)); - - if (element.Name.NamespaceName == string.Empty) - { - element.Name = xmlns + element.Name.LocalName; - } - - foreach (var e in element.Elements()) - { - e.SetDefaultXmlNamespace(xmlns); - } - } - - /// - /// Gets a sequence containing every element with the name equal to . - /// - /// The used to read the XML - /// The name of the elements to return - /// The flag indicating whether the name should be looked up in a case sensitive manner - /// The sequence containing all the elements matching the - public static IEnumerable GetEelements(this XmlReader reader, XName name, bool ignoreCase = true) - { - Ensure.NotNull(reader, nameof(reader)); - Ensure.NotNull(name, nameof(name)); - - var compPolicy = ignoreCase - ? StringComparison.InvariantCultureIgnoreCase - : StringComparison.InvariantCulture; - - reader.MoveToElement(); - while (reader.Read()) - { - while (reader.NodeType == XmlNodeType.Element - && reader.Name.Equals(name.LocalName, compPolicy)) - { - yield return (XElement)XNode.ReadFrom(reader); - } - } - } - - /// - /// Converts the content of the given to . - /// - public static DynamicDictionary ToDynamic(this XmlReader reader, bool ignoreCase = true) + public static bool IsNotNullOrEmptyOrWhiteSpace(this string value) { - Ensure.NotNull(reader, nameof(reader)); - - var result = new DynamicDictionary(ignoreCase); - var elements = new List(); - result["Elements"] = elements; - - reader.MoveToElement(); - while (reader.Read()) - { - while (reader.NodeType == XmlNodeType.Element) - { - var element = (XElement)XNode.ReadFrom(reader); - elements.Add(element); - } - } - - return result; + return !value.IsNullOrEmptyOrWhiteSpace(); } } } diff --git a/src/Maple.Core/Helpers/NetworkHelper.cs b/src/Maple.Core/Helpers/NetworkHelper.cs deleted file mode 100644 index 611ed66..0000000 --- a/src/Maple.Core/Helpers/NetworkHelper.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Net; -using System.Net.NetworkInformation; -using System.Net.Sockets; - -namespace Maple.Core -{ - /// - /// Provides a set of methods to help work with network related activities. - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - public static class NetworkHelper - { - /// - /// Returns the LocalHost Fully Qualified Domain Name - /// - /// - /// The localhost Fully Qualified Domain Name - public static string GetFQDN() - { - var domainName = IPGlobalProperties.GetIPGlobalProperties().DomainName; - var hostName = Dns.GetHostName(); - - domainName = "." + domainName; - if (!hostName.EndsWith(domainName)) - { - hostName += domainName; - } - - return hostName; - } - - /// - /// Gets the local IP address for the machine or VM running the code. - /// - /// - /// - /// - /// The local IP address - public static IPAddress GetLocalIPAddress() - { - using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0)) - { - // can be any address - socket.Connect("10.0.2.4", 65530); - var endPoint = socket.LocalEndPoint as IPEndPoint; - // ReSharper disable once PossibleNullReferenceException - return IPAddress.Parse(endPoint.Address.ToString()); - } - } - - /// - /// Gets all the IP (v4 and not v6) addresses of the local computer together with - /// the interface to which the IP belongs. - /// - /// - public static IDictionary GetLocalIPAddresses() - { - // Get a list of all network interfaces (usually one per network card, dial-up, and VPN connection) - var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); - - var result = new Dictionary(); - foreach (var networkInterface in networkInterfaces) - { - // Read the IP configuration for each network - var properties = networkInterface.GetIPProperties(); - - // Each network interface may have multiple IP addresses - foreach (var address in properties.UnicastAddresses) - { - // We're only interested in IPv4 addresses for now - if (address.Address.AddressFamily != AddressFamily.InterNetwork) { continue; } - - // Ignore loopback addresses (e.g., 127.0.0.1) - if (IPAddress.IsLoopback(address.Address)) { continue; } - - result.Add(address.Address, networkInterface.Name); - } - } - return result; - } - } -} diff --git a/src/Maple.Core/Helpers/ProcessHelper.cs b/src/Maple.Core/Helpers/ProcessHelper.cs deleted file mode 100644 index 8205735..0000000 --- a/src/Maple.Core/Helpers/ProcessHelper.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Maple.Core -{ - /// - /// Provides a set of methods to help work with a . - /// - public static class ProcessHelper - { - /// - /// Starts a Process Asynchronously. - /// - /// - /// The information for the process to run. - /// The cancellation token. - /// A task representing the started process which you can await until process exits. - public static Task ExecuteAsync(ProcessStartInfo processInfo, CancellationToken cToken = default(CancellationToken)) - { - Ensure.NotNull(processInfo, nameof(processInfo)); - - processInfo.UseShellExecute = false; - processInfo.CreateNoWindow = true; - processInfo.RedirectStandardOutput = true; - processInfo.RedirectStandardError = true; - - var process = new Process - { - EnableRaisingEvents = true, - StartInfo = processInfo - }; - - var tcs = new TaskCompletionSource(); - var standardOutput = new List(); - var standardError = new List(); - - var standardOutputResults = new TaskCompletionSource(); - process.OutputDataReceived += (sender, args) => - { - if (args.Data != null) - standardOutput.Add(args.Data); - else - standardOutputResults.SetResult(standardOutput.ToArray()); - }; - - var standardErrorResults = new TaskCompletionSource(); - process.ErrorDataReceived += (sender, args) => - { - if (args.Data != null) - standardError.Add(args.Data); - else - standardErrorResults.SetResult(standardError.ToArray()); - }; - - process.Exited += (sender, args) => - { - // Since the Exited event can happen asynchronously to the output and error events, - // we use the task results for stdout/stderr to ensure they are both closed - tcs.TrySetResult(new ProcessExecutionResult(process, standardOutputResults.Task.Result, standardErrorResults.Task.Result)); - }; - - using (cToken.Register(() => - { - tcs.TrySetCanceled(); - try - { - if (!process.HasExited) { process.Kill(); } - } - catch (InvalidOperationException) { } - })) - { - cToken.ThrowIfCancellationRequested(); - - if (!process.Start()) - { - tcs.TrySetException(new InvalidOperationException("Failed to start the process.")); - } - - process.BeginOutputReadLine(); - process.BeginErrorReadLine(); - return tcs.Task; - } - } - - /// - /// Starts a process represented by asynchronously. - /// - /// - /// The path to the process. - /// The arguments to be passed to the process. - /// The cancellation token. - /// A task representing the started process which you can await until process exits. - public static Task ExecuteAsync(string processPath, string args, CancellationToken cToken = default(CancellationToken)) - { - Ensure.NotNullOrEmptyOrWhiteSpace(processPath); - return ExecuteAsync(new ProcessStartInfo(processPath, args), cToken); - } - - /// - /// Starts a process represented by and asynchronously. - /// - /// - /// The path to the process. - /// The arguments to be passed to the process. - /// The cancellation token. - /// A task representing the started process which you can await until process exits. - public static Task ExecuteAsync(FileInfo processPath, string args, CancellationToken cToken = default(CancellationToken)) - { - Ensure.NotNull(processPath, nameof(processPath)); - return ExecuteAsync(new ProcessStartInfo(processPath.FullName, args), cToken); - } - } -} diff --git a/src/Maple.Core/Maple.Core.csproj b/src/Maple.Core/Maple.Core.csproj index ca05fef..d70fc17 100644 --- a/src/Maple.Core/Maple.Core.csproj +++ b/src/Maple.Core/Maple.Core.csproj @@ -23,6 +23,7 @@ 4 AnyCPU false + 7.2 pdbonly @@ -44,6 +45,9 @@ 2.2.0 + + 7.1.0.5212 + 1.7.8 @@ -74,17 +78,12 @@ - - - - - @@ -123,7 +122,6 @@ - @@ -135,8 +133,6 @@ - - True True @@ -155,7 +151,6 @@ - diff --git a/src/Maple.Core/Observables/Base/ObservableObject.cs b/src/Maple.Core/Observables/Base/ObservableObject.cs index 163ab2c..b8d7fb7 100644 --- a/src/Maple.Core/Observables/Base/ObservableObject.cs +++ b/src/Maple.Core/Observables/Base/ObservableObject.cs @@ -27,7 +27,7 @@ protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = protected virtual bool SetValue(ref T field, T value, Action OnChanging = null, Action OnChanged = null, [CallerMemberName]string propertyName = null) { - if (EqualityComparer.Default.Equals(field, value)) + if (EqualityComparer.Default.Equals(field, value)) // TODO add cache for equality comparer as readonly field return false; OnChanging?.Invoke(); diff --git a/src/Maple.Core/Observables/NotifyTaskCompletion.cs b/src/Maple.Core/Observables/NotifyTaskCompletion.cs index cdc8650..792982e 100644 --- a/src/Maple.Core/Observables/NotifyTaskCompletion.cs +++ b/src/Maple.Core/Observables/NotifyTaskCompletion.cs @@ -11,7 +11,7 @@ public sealed class NotifyTaskCompletion : INotifyPropertyChanged public Task Task { get; private set; } public Task TaskCompletion { get; private set; } - public TResult Result => (Task.Status == TaskStatus.RanToCompletion) ? Task.Result : default(TResult); + public TResult Result => (Task.Status == TaskStatus.RanToCompletion) ? Task.Result : default; public TaskStatus Status { get { return Task.Status; } } public bool IsCompleted { get { return Task.IsCompleted; } } diff --git a/src/Maple.Core/Observables/RangeObservableCollection.cs b/src/Maple.Core/Observables/RangeObservableCollection.cs index ce8f7ac..a25725a 100644 --- a/src/Maple.Core/Observables/RangeObservableCollection.cs +++ b/src/Maple.Core/Observables/RangeObservableCollection.cs @@ -1,11 +1,10 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; -using System.Linq; using System.Runtime.CompilerServices; + using Maple.Domain; using Maple.Localization.Properties; @@ -47,11 +46,6 @@ private void RaiseCollectionChanged(NotifyCollectionChangedEventArgs param) base.OnCollectionChanged(param); } - public virtual void AddRange(IList items) - { - AddRange(items.Cast()); - } - public virtual void AddRange(IEnumerable items) { if (items == null) @@ -80,34 +74,6 @@ public virtual void RemoveRange(IEnumerable items) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } - public virtual void RemoveRange(IList items) - { - if (items == null) - throw new ArgumentNullException(nameof(items), $"{nameof(items)} {Resources.IsRequired}"); - - using (_busyStack.GetToken()) - { - foreach (var item in items.Cast()) - Remove(item); - } - - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - } - - public virtual void RemoveRange(IList items) - { - if (items == null) - throw new ArgumentNullException(nameof(items), $"{nameof(items)} {Resources.IsRequired}"); - - using (_busyStack.GetToken()) - { - foreach (var item in items) - Remove(item); - } - - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - } - public void OnPropertyChanged([CallerMemberName]string propertyName = null) { OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); @@ -122,10 +88,5 @@ private void RaisePropertyChanged(PropertyChangedEventArgs param) { base.OnPropertyChanged(param); } - - public void AddRange(IList items) - { - AddRange((IEnumerable)items); - } } } diff --git a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs index daba5eb..f179661 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseDataListViewModel.cs @@ -10,9 +10,8 @@ namespace Maple.Core { // TODO add virtualization here - // public abstract class BaseDataListViewModel : BaseListViewModel - where TViewModel : VirtualizationViewModel, ISequence + where TViewModel : VirtualizationViewModel, ISequence where TModel : class, IEntity { protected readonly ISequenceService _sequenceProvider; @@ -22,12 +21,6 @@ public abstract class BaseDataListViewModel : protected IRepository Repository { get; } private ICollectionView _view; - /// - /// For grouping, sorting and filtering - /// - /// - /// The view. - /// public ICollectionView View { get { return _view; } @@ -46,29 +39,21 @@ protected BaseDataListViewModel(ViewModelServiceContainer container) View = new VirtualizingCollectionViewSource(container, Items); } - /// - /// Removes the specified item. - /// - /// The item. - public override void Remove(TViewModel container) + public override void Remove(TViewModel item) { - if (container == null) - throw new ArgumentNullException(nameof(container), $"{nameof(container)} {Resources.IsRequired}"); + if (item == null) + throw new ArgumentNullException(nameof(item), $"{nameof(item)} {Resources.IsRequired}"); using (BusyStack.GetToken()) { - while (Items.Contains(container)) + while (Items.Contains(item)) { - Repository.Delete(container.ViewModel.Model); - base.Remove(container); + Repository.Delete(item.ViewModel.Model); + base.Remove(item); } } } - /// - /// Removes the range. - /// - /// The items. public override void RemoveRange(IEnumerable items) { if (items == null) @@ -81,11 +66,6 @@ public override void RemoveRange(IEnumerable items) } } - /// - /// Removes the range. - /// - /// The items. - /// items public override void RemoveRange(IList items) { if (items == null) @@ -98,14 +78,14 @@ public override void RemoveRange(IList items) } } - public override void Add(TViewModel viewModel) + public override void Add(TViewModel item) { - if (viewModel == null) - throw new ArgumentNullException(nameof(viewModel), $"{nameof(viewModel)} {Resources.IsRequired}"); + if (item == null) + throw new ArgumentNullException(nameof(item), $"{nameof(item)} {Resources.IsRequired}"); var sequence = _sequenceProvider.Get(Items.Cast().ToList()); - viewModel.Sequence = sequence; - base.Add(viewModel); + item.Sequence = sequence; + base.Add(item); } public override void AddRange(IEnumerable items) diff --git a/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs index c3709ec..ff2ee14 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseDataViewModel.cs @@ -3,7 +3,7 @@ namespace Maple.Core { - public abstract class BaseDataViewModel : BaseViewModel + public abstract class BaseDataViewModel : BaseViewModel where TModel : class { protected ChangeTracker ChangeTracker { get; } @@ -14,19 +14,6 @@ public bool IsChanged get { return ChangeTracker.HasChanged; } } - protected override bool SetValue(ref T field, T value, Action OnChanging = null, Action OnChanged = null, [CallerMemberName] string propertyName = null) - { - var result = base.SetValue(ref field, value, OnChanging, OnChanged, propertyName); - - if (result) - { - if (!SkipChangeTracking && ChangeTracker.Update(value, propertyName)) - OnPropertyChanged(nameof(IsChanged)); - } - - return result; - } - protected BaseDataViewModel(TModel model, IMessenger messenger) : base(model, messenger) { @@ -37,5 +24,17 @@ protected BaseDataViewModel(TModel model, IMessenger messenger) SkipChangeTracking = false; } + + protected override bool SetValue(ref T field, T value, Action OnChanging = null, Action OnChanged = null, [CallerMemberName] string propertyName = null) + { + var result = base.SetValue(ref field, value, OnChanging, OnChanged, propertyName); + + if (result && !SkipChangeTracking && ChangeTracker.Update(value, propertyName)) + { + OnPropertyChanged(nameof(IsChanged)); + } + + return result; + } } } diff --git a/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs b/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs index d2c0341..66e70fc 100644 --- a/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/BaseListViewModel.cs @@ -105,12 +105,12 @@ public virtual bool CanRemoveRange(IEnumerable items) public virtual bool CanRemoveRange(IList items) { - return items == null ? false : CanRemoveRange(items.Cast()); + return !(items == null) && CanRemoveRange(items.Cast()); } public virtual void Clear() { - SelectedItem = default(TViewModel); + SelectedItem = default; using (BusyStack.GetToken()) Items.Clear(); diff --git a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs index 8ae71e0..a790495 100644 --- a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataListViewModel.cs @@ -10,7 +10,7 @@ namespace Maple.Core { // TODO add logic for handling INotifyDataErrorInfo for children and on this public abstract class ValidableBaseDataListViewModel : BaseDataListViewModel, ILoadableViewModel, IVirtualizedListViewModel - where TViewModel : VirtualizationViewModel, ISequence + where TViewModel : VirtualizationViewModel, ISequence where TModel : class, IEntity, new() { public bool IsLoaded { get; protected set; } diff --git a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs index bbdf31e..9f99568 100644 --- a/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/ValidableBaseDataViewModel.cs @@ -14,8 +14,8 @@ namespace Maple.Core { - public abstract class ValidableBaseDataViewModel : BaseDataViewModel, INotifyDataErrorInfo - where TViewModel : BaseDataViewModel, ISequence + public abstract class ValidableBaseDataViewModel : BaseDataViewModel, INotifyDataErrorInfo + where TViewModel : BaseDataViewModel, ISequence where TModel : class, IEntity { protected bool SkipValidation { get; set; } @@ -62,13 +62,7 @@ public IEnumerable GetErrors(string propertyName) return Messages[propertyName].Errors.Select(p => p.ErrorMessage); } - /// - /// Validates the specified property name. - /// - /// Name of the property. - /// - /// - public virtual void Validate([CallerMemberName] string propertyName = null) + public virtual void Validate(string propertyName) { if (SkipValidation) return; @@ -83,7 +77,7 @@ protected override void OnPropertyChanged([CallerMemberName] string propertyName { base.OnPropertyChanged(propertyName); - if (this == null || SkipValidation) + if (SkipValidation) return; AddOrUpdateValidationResults(Validator.Validate(this, propertyName), propertyName); diff --git a/src/Maple.Core/Observables/ViewModels/ViewModel.cs b/src/Maple.Core/Observables/ViewModels/ViewModel.cs index 99a892c..2c1a5f5 100644 --- a/src/Maple.Core/Observables/ViewModels/ViewModel.cs +++ b/src/Maple.Core/Observables/ViewModels/ViewModel.cs @@ -1,12 +1,12 @@ using System; using System.Collections.Generic; + using Maple.Localization.Properties; namespace Maple.Core { public abstract class ViewModel : ObservableObject, IDisposable { - // TODO cache equality comparer protected IMessenger Messenger { get; } protected BusyStack BusyStack { get; } @@ -42,7 +42,9 @@ protected virtual void Dispose(bool disposing) if (disposing) { +#pragma warning disable S1066 // Collapsible "if" statements should be merged if (MessageTokens != null) +#pragma warning restore S1066 // Collapsible "if" statements should be merged { foreach (var token in MessageTokens) Messenger.Unsubscribe(token); diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs index 68f537a..4c259db 100644 --- a/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs +++ b/src/Maple.Core/Observables/Virtualization/VirtualizationViewModel.cs @@ -7,10 +7,10 @@ namespace Maple.Core { // container for one viewmodel - public class VirtualizationViewModel : ObservableObject + public class VirtualizationViewModel : ObservableObject where TModel : class { - private readonly IDataProvider, TKeyDataType> _dataProvider; + private readonly IDataProvider, TKeyDataType> _dataProvider; private readonly TKeyDataType _id; @@ -35,8 +35,8 @@ public bool IsBusy private set { SetValue(ref _isBusy, value); } } - private BaseDataViewModel _viewModel; - public BaseDataViewModel ViewModel + private BaseDataViewModel _viewModel; + public BaseDataViewModel ViewModel { get { return _viewModel; } set { SetValue(ref _viewModel, value); } @@ -56,7 +56,7 @@ public IAsyncCommand ExpandCommand private set { SetValue(ref _expandCommand, value); } } - public VirtualizationViewModel(TKeyDataType id, IDataProvider, TKeyDataType> dataProvider) + public VirtualizationViewModel(TKeyDataType id, IDataProvider, TKeyDataType> dataProvider) { _id = id; _dataProvider = dataProvider ?? throw new ArgumentNullException(nameof(dataProvider), $"{nameof(dataProvider)} {Resources.IsRequired}"); diff --git a/src/Maple.Core/Observables/Virtualization/VirtualizingCollectionViewSource.cs b/src/Maple.Core/Observables/Virtualization/VirtualizingCollectionViewSource.cs index d0fe8fc..590ac79 100644 --- a/src/Maple.Core/Observables/Virtualization/VirtualizingCollectionViewSource.cs +++ b/src/Maple.Core/Observables/Virtualization/VirtualizingCollectionViewSource.cs @@ -5,8 +5,6 @@ using System.Windows.Data; using System.Windows.Threading; -using Maple.Localization.Properties; - namespace Maple.Core { public sealed class VirtualizingCollectionViewSource : ListCollectionView @@ -21,8 +19,11 @@ public sealed class VirtualizingCollectionViewSource : ListCollectionView public VirtualizingCollectionViewSource(ViewModelServiceContainer container, IList list) : base(list) { - _cache = container.Cache ?? throw new ArgumentNullException(nameof(container.Cache), $"{nameof(container.Cache)} {Resources.IsRequired}"); - _policy = container.CacheItemPolicy ?? throw new ArgumentNullException(nameof(container.CacheItemPolicy), $"{nameof(container.CacheItemPolicy)} {Resources.IsRequired}"); + if (container == null) + throw new ArgumentNullException(nameof(container)); + + _cache = container.Cache; + _policy = container.CacheItemPolicy; _deferredItems = new HashSet(); _sponsor = list as IVirtualizedListViewModel; diff --git a/src/Maple.Core/ProcessExecutionResult.cs b/src/Maple.Core/ProcessExecutionResult.cs deleted file mode 100644 index ab1f89f..0000000 --- a/src/Maple.Core/ProcessExecutionResult.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Diagnostics; - -namespace Maple.Core -{ - /// - /// Represents the result of executing a process. - /// - public sealed class ProcessExecutionResult : IDisposable - { - private Process _process; - private bool _disposed; - - internal ProcessExecutionResult(Process process, string[] standardOutput, string[] standardError) - { - _process = Ensure.NotNull(process, nameof(process)); - - PID = _process.Id; - ExecutionTime = _process.ExitTime - _process.StartTime; - StandardOutput = Ensure.NotNull(standardOutput, nameof(standardOutput)); - StandardError = Ensure.NotNull(standardError, nameof(standardError)); - } - - /// - /// Gets the process ID. - /// - // ReSharper disable once InconsistentNaming - public int PID { get; } - - /// - /// Gets the execution time of the process. - /// - public TimeSpan ExecutionTime { get; } - - /// - /// Gets the standard output of the process. - /// - public string[] StandardOutput { get; } - - /// - /// Gets the standard error of the process. - /// - public string[] StandardError { get; } - - /// - /// Read the value of the process property identified by the given . - /// - public T ReadProcessInfo(Func selector) - { - return selector(_process); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases all resources used by the underlying process. - /// - private void Dispose(bool disposing) - { - if (_disposed) - return; - - if (disposing) - { - if (_process != null) - { - _process.Dispose(); - _process = null; - } - } - - _disposed = true; - } - } -} diff --git a/src/Maple.Core/Services/Caching/ICachingService.cs b/src/Maple.Core/Services/Caching/ICachingService.cs index d59df0b..0e1d6eb 100644 --- a/src/Maple.Core/Services/Caching/ICachingService.cs +++ b/src/Maple.Core/Services/Caching/ICachingService.cs @@ -1,6 +1,6 @@ namespace Maple.Core { - public interface ICachingService + public interface ICachingService { bool Contains(TKey key); bool Add(TKey key, TObject item); diff --git a/src/Maple.Core/Services/Caching/MemoryCacheService.cs b/src/Maple.Core/Services/Caching/MemoryCacheService.cs index 6303cdd..94e8aab 100644 --- a/src/Maple.Core/Services/Caching/MemoryCacheService.cs +++ b/src/Maple.Core/Services/Caching/MemoryCacheService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.Caching; + using Maple.Localization.Properties; namespace Maple.Core @@ -34,12 +35,12 @@ protected MemoryCacheService(MemoryCache cache, IVirtualizedListViewModel virtua _cache = cache ?? throw new ArgumentNullException(nameof(cache), $"{nameof(cache)} {Resources.IsRequired}"); } - public bool Add(TKey key, TObject viewModel) + public bool Add(TKey key, TObject item) { - if (viewModel == null) - throw new ArgumentNullException(nameof(viewModel), $"{nameof(viewModel)} {Resources.IsRequired}"); + if (item == null) + throw new ArgumentNullException(nameof(item), $"{nameof(item)} {Resources.IsRequired}"); - var result = _cache.Add(new CacheItem(GetInternalKey(key), viewModel), _policy); + var result = _cache.Add(new CacheItem(GetInternalKey(key), item), _policy); if (result) _trackedEntries.Add(key); @@ -71,10 +72,6 @@ public bool Remove(TKey key) } public abstract void CacheRemovedCallback(CacheEntryRemovedArguments arguments); - //{ - // _virtualizationProvider.DeflateItem(arguments.CacheItem.Value); - //} - private string GetInternalKey(TKey key) { diff --git a/src/Maple.Core/Services/Caching/SimpleStaticCacheService.cs b/src/Maple.Core/Services/Caching/SimpleStaticCacheService.cs index e37bff4..7db35cc 100644 --- a/src/Maple.Core/Services/Caching/SimpleStaticCacheService.cs +++ b/src/Maple.Core/Services/Caching/SimpleStaticCacheService.cs @@ -9,9 +9,9 @@ public bool Contains(TPrimaryKeyType key) return ContainsKey(key); } - bool ICachingService.Add(TPrimaryKeyType key, TViewModel viewModel) + bool ICachingService.Add(TPrimaryKeyType key, TViewModel item) { - Add(key, viewModel); + Add(key, item); return true; } diff --git a/src/Maple.Core/Services/Caching/WeakReferenceCache.cs b/src/Maple.Core/Services/Caching/WeakReferenceCache.cs index f269b3a..141b61d 100644 --- a/src/Maple.Core/Services/Caching/WeakReferenceCache.cs +++ b/src/Maple.Core/Services/Caching/WeakReferenceCache.cs @@ -20,11 +20,10 @@ public bool Add(TKey key, TObject item) public bool Add(TKey key, TObject item, bool isStrongReference) { - // can't accept IDisposeable, since we dont know when the object will be disposed and we cant call Dispose on it if (item is IDisposable) - throw new ArgumentException(); + throw new ArgumentException("can't accept IDisposeable, since we dont know when the object will be disposed and we cant call Dispose on it"); - _references.AddOrUpdate(key, new WeakReference(item), (existingKey, existingEntry) => existingEntry = new WeakReference(item)); + _references.AddOrUpdate(key, new WeakReference(item), (existingKey, existingEntry) => new WeakReference(item)); return true; @@ -39,7 +38,7 @@ public bool Add(TKey key, TObject item, bool isStrongReference) public bool TryGetValue(TKey key, out TObject item) { - item = default(TObject); + item = default; if (_references.TryGetValue(key, out var reference)) return reference.TryGetTarget(out item); diff --git a/src/Maple.Core/Services/Localization/LocalizationDTO.cs b/src/Maple.Core/Services/Localization/LocalizationDTO.cs index c77666b..019b3b4 100644 --- a/src/Maple.Core/Services/Localization/LocalizationDTO.cs +++ b/src/Maple.Core/Services/Localization/LocalizationDTO.cs @@ -14,13 +14,13 @@ namespace Maple.Core /// /// /// - public class LocalizationDTO : ObservableObject, INotifyPropertyChanged, IDisposable + public class LocalizationDto : ObservableObject, IDisposable { private readonly string _key; private readonly ILocalizationService _service; private readonly bool _toUpper; - public LocalizationDTO(ILocalizationService service, string key, bool toUpper) + public LocalizationDto(ILocalizationService service, string key, bool toUpper) { _service = service ?? throw new ArgumentNullException(nameof(service), $"{nameof(service)} {Resources.IsRequired}"); _key = key ?? throw new ArgumentNullException(nameof(key), $"{nameof(key)} {Resources.IsRequired}"); diff --git a/src/Maple.Core/Services/Logging/DetailLoggingService.cs b/src/Maple.Core/Services/Logging/DetailLoggingService.cs deleted file mode 100644 index 323923f..0000000 --- a/src/Maple.Core/Services/Logging/DetailLoggingService.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using Maple.Domain; -using Maple.Localization.Properties; - -namespace Maple.Core -{ - /// - /// Facade that generates a diagnostic report when exceptions are being thrown around and forwards report and exceptions to the log - /// - public class DetailLoggingService : ILoggingService - { - private readonly ILoggingService _log; - - private bool _hasLoggedException = false; - - public DetailLoggingService(ILoggingService log) - { - _log = log ?? throw new ArgumentNullException(nameof(log), $"{nameof(log)} {Resources.IsRequired}"); - } - - public void Error(object message) - { - if (!_hasLoggedException) - _log.Error(DiagnosticReport.Generate(DiagnosticReportType.Full)); - - _log.Error(message); - - _hasLoggedException = true; - } - - public void Error(object message, Exception exception) - { - if (!_hasLoggedException) - _log.Error(DiagnosticReport.Generate(DiagnosticReportType.Full)); - - _log.Error(message, exception); - - _hasLoggedException = true; - } - - public void Fatal(object message) - { - if (!_hasLoggedException) - _log.Fatal(DiagnosticReport.Generate(DiagnosticReportType.Full)); - - _log.Fatal(message); - - _hasLoggedException = true; - } - - public void Fatal(object message, Exception exception) - { - if (!_hasLoggedException) - _log.Fatal(DiagnosticReport.Generate(DiagnosticReportType.Full)); - - _log.Fatal(message, exception); - - _hasLoggedException = true; - } - - public void Info(object message) - { - _log.Info(message); - } - - public void Info(object message, Exception exception) - { - _log.Info(message, exception); - } - - public void Warn(object message) - { - _log.Warn(message); - } - - public void Warn(object message, Exception exception) - { - _log.Warn(message, exception); - } - } -} diff --git a/src/Maple.Core/Services/Logging/LoggingService.cs b/src/Maple.Core/Services/Logging/LoggingService.cs index 88c8670..b6b2914 100644 --- a/src/Maple.Core/Services/Logging/LoggingService.cs +++ b/src/Maple.Core/Services/Logging/LoggingService.cs @@ -1,5 +1,7 @@ using System; + using log4net; + using Maple.Domain; namespace Maple.Core @@ -85,8 +87,6 @@ public void Info(object message) /// The exception. public void Info(object message, Exception exception) { - var text = (string)message; - _log.Info(message, exception); } diff --git a/src/Maple.Core/Services/Mapping/Base/IBaseMapper.cs b/src/Maple.Core/Services/Mapping/Base/IBaseMapper.cs index 793a1f2..97fc5fd 100644 --- a/src/Maple.Core/Services/Mapping/Base/IBaseMapper.cs +++ b/src/Maple.Core/Services/Mapping/Base/IBaseMapper.cs @@ -1,7 +1,7 @@ namespace Maple.Core { public interface IBaseMapper - where TVieModel : BaseDataViewModel + where TVieModel : BaseDataViewModel where TDataModel : class { TVieModel Get(TDataModel model); diff --git a/src/Maple.Core/Services/Mapping/MediaItemMapper.cs b/src/Maple.Core/Services/Mapping/MediaItemMapper.cs index 4ffc84c..3fcd164 100644 --- a/src/Maple.Core/Services/Mapping/MediaItemMapper.cs +++ b/src/Maple.Core/Services/Mapping/MediaItemMapper.cs @@ -1,5 +1,7 @@ using AutoMapper; + using FluentValidation; + using Maple.Domain; using Maple.Localization.Properties; @@ -50,19 +52,24 @@ public MediaItemModel GetDataNewMediaItem(PlaylistModel playlist) }; } - public MediaItem Get(MediaItemModel mediaitem) + public MediaItem Get(MediaItemModel model) { - return new MediaItem(mediaitem, _validator, _messenger); + if (model == null) + { + throw new System.ArgumentNullException(nameof(model)); + } + + return new MediaItem(model, _validator, _messenger); } /// /// Gets the data. /// - /// The mediaitem. + /// The mediaitem. /// - public MediaItemModel GetData(MediaItem mediaitem) + public MediaItemModel GetData(MediaItem viewModel) { - return mediaitem.Model; + return viewModel.Model; } } } diff --git a/src/Maple.Core/Services/Mapping/MediaPlayerMapper.cs b/src/Maple.Core/Services/Mapping/MediaPlayerMapper.cs index 76a3dd3..e7a6b92 100644 --- a/src/Maple.Core/Services/Mapping/MediaPlayerMapper.cs +++ b/src/Maple.Core/Services/Mapping/MediaPlayerMapper.cs @@ -1,6 +1,9 @@ using System; + using AutoMapper; + using FluentValidation; + using Maple.Domain; using Maple.Localization.Properties; @@ -22,7 +25,7 @@ public MediaPlayerMapper(ViewModelServiceContainer container, IMediaPlayer media protected override void InitializeMapper() { - var config = new MapperConfiguration(cfg => // TODO mapper configuration + var config = new MapperConfiguration(cfg => { }); diff --git a/src/Maple.Core/Services/Mapping/PlaylistMapper.cs b/src/Maple.Core/Services/Mapping/PlaylistMapper.cs index 190024f..230628f 100644 --- a/src/Maple.Core/Services/Mapping/PlaylistMapper.cs +++ b/src/Maple.Core/Services/Mapping/PlaylistMapper.cs @@ -1,6 +1,9 @@ using System; + using AutoMapper; + using FluentValidation; + using Maple.Domain; using Maple.Localization.Properties; @@ -56,9 +59,14 @@ public Playlist Get(PlaylistModel model) return new Playlist(_container, _validator, _dialogViewModel, _mediaItemMapper, model); } - public PlaylistModel GetData(Playlist mediaitem) + public PlaylistModel GetData(Playlist viewModel) { - return mediaitem.Model; + if (viewModel == null) + { + throw new ArgumentNullException(nameof(viewModel)); + } + + return viewModel.Model; } } } diff --git a/src/Maple.Core/Services/Validation/Base/BaseValidator.cs b/src/Maple.Core/Services/Validation/Base/BaseValidator.cs index 492664f..f8729ac 100644 --- a/src/Maple.Core/Services/Validation/Base/BaseValidator.cs +++ b/src/Maple.Core/Services/Validation/Base/BaseValidator.cs @@ -7,7 +7,7 @@ namespace Maple.Core { - public abstract class BaseValidator : AbstractValidator, IValidator + public abstract class BaseValidator : AbstractValidator { protected readonly ILocalizationService _translationService; diff --git a/src/Maple.Core/Services/Validation/MediaItemValidator.cs b/src/Maple.Core/Services/Validation/MediaItemValidator.cs index 23b9856..e32e73f 100644 --- a/src/Maple.Core/Services/Validation/MediaItemValidator.cs +++ b/src/Maple.Core/Services/Validation/MediaItemValidator.cs @@ -4,7 +4,7 @@ namespace Maple.Core { - public class MediaItemValidator : BaseValidator, IValidator + public class MediaItemValidator : BaseValidator { public MediaItemValidator(ILocalizationService translationService) : base(translationService) diff --git a/src/Maple.Core/Services/Validation/MediaPlayerValidator.cs b/src/Maple.Core/Services/Validation/MediaPlayerValidator.cs index c872e14..043c97b 100644 --- a/src/Maple.Core/Services/Validation/MediaPlayerValidator.cs +++ b/src/Maple.Core/Services/Validation/MediaPlayerValidator.cs @@ -4,7 +4,7 @@ namespace Maple.Core { - public class MediaPlayerValidator : BaseValidator, IValidator + public class MediaPlayerValidator : BaseValidator { public MediaPlayerValidator(ILocalizationService translationService) : base(translationService) diff --git a/src/Maple.Core/Services/Validation/PlaylistValidator.cs b/src/Maple.Core/Services/Validation/PlaylistValidator.cs index cbc421d..1a6612c 100644 --- a/src/Maple.Core/Services/Validation/PlaylistValidator.cs +++ b/src/Maple.Core/Services/Validation/PlaylistValidator.cs @@ -4,7 +4,7 @@ namespace Maple.Core { - public class PlaylistValidator : BaseValidator, IValidator + public class PlaylistValidator : BaseValidator { public PlaylistValidator(ILocalizationService translationService, IValidator mediaItemValidator) : base(translationService) diff --git a/src/Maple.Core/Services/Validation/PlaylistsValidator.cs b/src/Maple.Core/Services/Validation/PlaylistsValidator.cs index 804082c..43d567f 100644 --- a/src/Maple.Core/Services/Validation/PlaylistsValidator.cs +++ b/src/Maple.Core/Services/Validation/PlaylistsValidator.cs @@ -4,7 +4,7 @@ namespace Maple.Core { - public class PlaylistsValidator : BaseValidator, IValidator + public class PlaylistsValidator : BaseValidator { public PlaylistsValidator(ILocalizationService translationService, IValidator playlistValidator) : base(translationService) diff --git a/src/Maple.Core/ViewModels/Dialogs/Base/DialogBaseViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/Base/DialogBaseViewModel.cs index f306371..b0bbb11 100644 --- a/src/Maple.Core/ViewModels/Dialogs/Base/DialogBaseViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/Base/DialogBaseViewModel.cs @@ -7,7 +7,7 @@ namespace Maple.Core { public abstract class DialogBaseViewModel : ViewModel { - public EventHandler DialogClosed; + private EventHandler _dialogClosed; public ExceptionContentDialogViewModel ExceptionDialogViewModel { get; protected set; } public MessageContentDialogViewModel MessageDialogViewModel { get; protected set; } @@ -66,7 +66,7 @@ protected DialogBaseViewModel(IMessenger messenger) private void OnOpenChanged() { if (!IsOpen) - DialogClosed?.Invoke(this, EventArgs.Empty); + _dialogClosed?.Invoke(this, EventArgs.Empty); } /// @@ -86,7 +86,7 @@ public void Accept() /// public bool CanAccept() { - return CanClose() && (CanAcceptFunc?.Invoke() ?? true) == true; + return CanClose() && (CanAcceptFunc?.Invoke() ?? true); } /// @@ -106,7 +106,7 @@ public void Cancel() /// public bool CanCancel() { - return CanClose() && (CanCancelFunc?.Invoke() ?? true) == true; + return CanClose() && (CanCancelFunc?.Invoke() ?? true); } public Task Open() @@ -125,13 +125,13 @@ public async Task Open(CancellationToken token) void lambda(object s, EventArgs e) => tcs.TrySetResult(null); try { - DialogClosed += lambda; + _dialogClosed += lambda; IsOpen = true; // open dialog await tcs.Task.ConfigureAwait(false); // wait for dialog to close } finally { - DialogClosed -= lambda; + _dialogClosed -= lambda; registration.Dispose(); } } diff --git a/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs index f0862f4..e3c1788 100644 --- a/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FileBrowserContentDialogViewModel.cs @@ -6,8 +6,6 @@ namespace Maple.Core { public class FileBrowserContentDialogViewModel : ObservableObject { - private readonly FileSystemBrowserOptions _options; - private FileSystemViewModel _fileSystemViewModel; public FileSystemViewModel FileSystemViewModel { @@ -15,9 +13,8 @@ public FileSystemViewModel FileSystemViewModel private set { SetValue(ref _fileSystemViewModel, value); } } - public FileBrowserContentDialogViewModel(FileSystemViewModel fileSystemViewModel, FileSystemBrowserOptions options) + public FileBrowserContentDialogViewModel(FileSystemViewModel fileSystemViewModel) { - _options = options ?? throw new ArgumentNullException(nameof(options), $"{nameof(options)} {Resources.IsRequired}"); FileSystemViewModel = fileSystemViewModel ?? throw new ArgumentNullException(nameof(fileSystemViewModel), $"{nameof(fileSystemViewModel)} {Resources.IsRequired}"); } } diff --git a/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs index d16c9c2..f96ebee 100644 --- a/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogContentViewModels/IO/FolderBrowserContentDialogViewModel.cs @@ -6,18 +6,15 @@ namespace Maple.Core { public class FolderBrowserContentDialogViewModel : ObservableObject { - private readonly FileSystemBrowserOptions _options; private FileSystemViewModel _fileSystemViewModel; - public FileSystemViewModel FileSystemViewModel { get { return _fileSystemViewModel; } private set { SetValue(ref _fileSystemViewModel, value); } } - public FolderBrowserContentDialogViewModel(FileSystemViewModel fileSystemViewModel, FileSystemBrowserOptions options) + public FolderBrowserContentDialogViewModel(FileSystemViewModel fileSystemViewModel) { - _options = options ?? throw new ArgumentNullException(nameof(options), $"{nameof(options)} {Resources.IsRequired}"); FileSystemViewModel = fileSystemViewModel ?? throw new ArgumentNullException(nameof(fileSystemViewModel), $"{nameof(fileSystemViewModel)} {Resources.IsRequired}"); } } diff --git a/src/Maple.Core/ViewModels/Dialogs/DialogViewModel.cs b/src/Maple.Core/ViewModels/Dialogs/DialogViewModel.cs index 8d8ac4d..6f95514 100644 --- a/src/Maple.Core/ViewModels/Dialogs/DialogViewModel.cs +++ b/src/Maple.Core/ViewModels/Dialogs/DialogViewModel.cs @@ -17,8 +17,6 @@ public class DialogViewModel : DialogBaseViewModel, IDialogViewModel private readonly IMediaItemMapper _mediaItemMapper; private readonly FileSystemViewModel _fileSystemViewModel; - private readonly Func _createMediaItemFactory; - public DialogViewModel(ILocalizationService translator, IYoutubeUrlParser service, IMediaItemMapper mediaItemMapper, IMessenger messenger, FileSystemViewModel fileSystemViewModel, Func createMediaItemFactory) : base(messenger) { @@ -26,7 +24,6 @@ public DialogViewModel(ILocalizationService translator, IYoutubeUrlParser servic _service = service ?? throw new ArgumentNullException(nameof(service), $"{nameof(service)} {Resources.IsRequired}"); _mediaItemMapper = mediaItemMapper ?? throw new ArgumentNullException(nameof(mediaItemMapper), $"{nameof(mediaItemMapper)} {Resources.IsRequired}"); _fileSystemViewModel = fileSystemViewModel ?? throw new ArgumentNullException(nameof(fileSystemViewModel), $"{nameof(fileSystemViewModel)} {Resources.IsRequired}"); - _createMediaItemFactory = createMediaItemFactory ?? throw new ArgumentNullException(nameof(createMediaItemFactory), $"{nameof(createMediaItemFactory)} {Resources.IsRequired}"); CloseDialogCommand = new RelayCommand(Close, () => CanClose()); @@ -89,7 +86,7 @@ public Task ShowExceptionDialog(Exception exception) throw new InvalidOperationException(Resources.DialogOpenAlready); var tuple = default((bool Result, IList Files)); - var viewModel = new FileBrowserContentDialogViewModel(_fileSystemViewModel, options); + var viewModel = new FileBrowserContentDialogViewModel(_fileSystemViewModel); TitleDetail = string.Empty; Context = viewModel; @@ -162,7 +159,7 @@ public Task ShowExceptionDialog(Exception exception) throw new InvalidOperationException(Resources.DialogOpenAlready); var tuple = default((bool Result, IFileSystemDirectory Directory)); - var viewModel = new FileBrowserContentDialogViewModel(_fileSystemViewModel, options); + var viewModel = new FileBrowserContentDialogViewModel(_fileSystemViewModel); TitleDetail = string.Empty; Context = viewModel; diff --git a/src/Maple.Core/ViewModels/MediaItems/CreateMediaItem.cs b/src/Maple.Core/ViewModels/MediaItems/CreateMediaItem.cs index 4fbf349..12093db 100644 --- a/src/Maple.Core/ViewModels/MediaItems/CreateMediaItem.cs +++ b/src/Maple.Core/ViewModels/MediaItems/CreateMediaItem.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using System.Windows.Input; + using Maple.Localization.Properties; using Maple.Youtube; @@ -11,8 +12,8 @@ namespace Maple.Core /// public class CreateMediaItem : BaseListViewModel { - private IYoutubeUrlParser _dataParsingService; - private IMediaItemMapper _mapper; + private readonly IYoutubeUrlParser _dataParsingService; + private readonly IMediaItemMapper _mapper; public ICommand ParseCommand { get; private set; } diff --git a/src/Maple.Core/ViewModels/MediaPlayer/Base/BasePlayer.cs b/src/Maple.Core/ViewModels/MediaPlayer/Base/BasePlayer.cs index 794f62c..0fc3f0d 100644 --- a/src/Maple.Core/ViewModels/MediaPlayer/Base/BasePlayer.cs +++ b/src/Maple.Core/ViewModels/MediaPlayer/Base/BasePlayer.cs @@ -37,7 +37,7 @@ protected BasePlayer(IMessenger messenger, AudioDevices audioDevices) { } - public abstract bool CanPlay(IMediaItem item); + public abstract bool CanPlay(IMediaItem mediaItem); public abstract bool IsPlaying { get; } diff --git a/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayer.cs b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayer.cs index 1663ad7..994751d 100644 --- a/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayer.cs +++ b/src/Maple.Core/ViewModels/MediaPlayer/MediaPlayer.cs @@ -6,14 +6,13 @@ using FluentValidation; -using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; namespace Maple.Core { [DebuggerDisplay("{Name}, {Sequence}")] - public class MediaPlayer : ValidableBaseDataViewModel, IDisposable, IChangeState, ISequence + public class MediaPlayer : ValidableBaseDataViewModel, IChangeState, ISequence { protected readonly ILocalizationService _manager; diff --git a/src/Maple.Core/ViewModels/Playlists/Playlist.cs b/src/Maple.Core/ViewModels/Playlists/Playlist.cs index b3ac333..d70e946 100644 --- a/src/Maple.Core/ViewModels/Playlists/Playlist.cs +++ b/src/Maple.Core/ViewModels/Playlists/Playlist.cs @@ -10,7 +10,6 @@ using FluentValidation; -using Maple.Core; using Maple.Domain; using Maple.Localization.Properties; @@ -19,11 +18,9 @@ namespace Maple.Core [DebuggerDisplay("{Title}, {Sequence}")] public class Playlist : ValidableBaseDataViewModel, IIsSelected, ISequence { - private readonly IMediaItemMapper _mediaItemMapper; private readonly ISequenceService _sequenceProvider; private readonly ILocalizationService _translator; private readonly IDialogViewModel _dialogViewModel; - private readonly object _itemsLock; private readonly Stack _history; public bool IsNew => Model.IsNew; @@ -163,9 +160,6 @@ public Playlist(ViewModelServiceContainer container, IValidator valida SkipChangeTracking = true; using (BusyStack.GetToken()) { - _itemsLock = new object(); - - _mediaItemMapper = mediaItemMapper ?? throw new ArgumentNullException(nameof(mediaItemMapper), $"{nameof(mediaItemMapper)} {Resources.IsRequired}"); _dialogViewModel = dialogViewModel ?? throw new ArgumentNullException(nameof(dialogViewModel), $"{nameof(dialogViewModel)} {Resources.IsRequired}"); _sequenceProvider = container.SequenceService; @@ -193,8 +187,6 @@ public Playlist(ViewModelServiceContainer container, IValidator valida RemoveRangeCommand = new RelayCommand(RemoveRange, CanRemoveRange); ClearCommand = new RelayCommand(() => Clear(), CanClear); - AddRange(_mediaItemMapper.GetMany(model.MediaItems)); - MessageTokens.Add(Messenger.Subscribe(OnPlaybackItemChanged, m => m.PlaylistId == Id && _items.Contains(m.Content))); Validate(); @@ -315,18 +307,13 @@ public virtual void AddRange(IEnumerable items) var added = false; var sequence = 0; var collection = items.ToList(); - var item = default(MediaItem); for (var i = 0; i < collection.Count; i++) { if (i == 0) sequence = _sequenceProvider.Get(Items.Select(p => (ISequence)p).ToList()); - item = collection[i]; - - if (item == null) - throw new ArgumentNullException(nameof(item), $"{nameof(item)} {Resources.IsRequired}"); - + var item = collection[i]; item.Sequence = sequence; AddInternal(item); sequence++; @@ -407,7 +394,7 @@ protected virtual bool CanRemoveRange(IEnumerable items) protected virtual bool CanRemoveRange(IList items) { - return items == null ? false : CanRemoveRange(items.Cast()); + return (items != null) && CanRemoveRange(items.Cast()); } /// @@ -452,7 +439,7 @@ private MediaItem NextRepeatNone() if (nextPossibleItems?.Any() == true) // try to find items after the current one { Items.ToList().ForEach(p => p.IsSelected = false); - var foundItem = nextPossibleItems.Where(q => q.Sequence == nextPossibleItems.Select(p => p.Sequence).Min()).First(); + var foundItem = nextPossibleItems.First(q => q.Sequence == nextPossibleItems.Select(p => p.Sequence).Min()); foundItem.IsSelected = true; return foundItem; } @@ -485,7 +472,7 @@ private MediaItem NextRepeatAll() if (nextPossibleItems.Any()) // try to find items after the current one { Items.ToList().ForEach(p => p.IsSelected = false); - var foundItem = nextPossibleItems.Where(q => q.Sequence == nextPossibleItems.Select(p => p.Sequence).Min()).First(); + var foundItem = nextPossibleItems.First(q => q.Sequence == nextPossibleItems.Select(p => p.Sequence).Min()); foundItem.IsSelected = true; return foundItem; } @@ -527,9 +514,6 @@ public virtual MediaItem Previous() { var previous = _history.Pop(); - //if (previous == SelectedItem?.Sequence) // the most recent item in the history, is the just played item, so we wanna skip that - // continue; - if (previous > -1) { var previousItems = Items.Where(p => p.Sequence == previous); // try to get the last played item diff --git a/src/Maple.Core/ViewModels/Settings/Cultures.cs b/src/Maple.Core/ViewModels/Settings/Cultures.cs index 13792ee..dc14a26 100644 --- a/src/Maple.Core/ViewModels/Settings/Cultures.cs +++ b/src/Maple.Core/ViewModels/Settings/Cultures.cs @@ -1,5 +1,6 @@ using System.Linq; using System.Threading.Tasks; + using Maple.Domain; using Maple.Localization.Properties; @@ -37,11 +38,6 @@ public Cultures(ViewModelServiceContainer container) MessageTokens.Add(Messenger.Subscribe>(UpdateCulture)); } - private void SyncCulture() - { - _manager.CurrentLanguage = SelectedItem.Model; - } - public Task Save() { _log.Info($"{Resources.Saving} {Resources.Options}"); diff --git a/src/Maple.Core/ViewModels/SplashScreenViewModel.cs b/src/Maple.Core/ViewModels/SplashScreenViewModel.cs index fb17511..f65871a 100644 --- a/src/Maple.Core/ViewModels/SplashScreenViewModel.cs +++ b/src/Maple.Core/ViewModels/SplashScreenViewModel.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Windows.Input; + using Maple.Domain; using Maple.Localization.Properties; @@ -8,6 +9,7 @@ namespace Maple.Core { public class SplashScreenViewModel : ObservableObject, ISplashScreenViewModel { + private readonly SubscriptionToken _subscriptionToken; private readonly IMessenger _messenger; private readonly Queue _queue; private System.Timers.Timer _timer; @@ -52,7 +54,7 @@ private SplashScreenViewModel() private SplashScreenViewModel(IMessenger messenger) : this() { _messenger = messenger ?? throw new ArgumentNullException(nameof(messenger), $"{nameof(messenger)} {Resources.IsRequired}"); - _messenger.Subscribe(LogMessageReceived); + _subscriptionToken = messenger.Subscribe(e => _queue.Enqueue(e.Content)); } public SplashScreenViewModel(IMessenger messenger, IVersionService version) : this(messenger) @@ -86,11 +88,6 @@ private bool CanLoad() return !IsDisposed; } - private void LogMessageReceived(LogMessageReceivedMessage e) - { - _queue.Enqueue(e.Content); - } - public void Dispose() { Dispose(true); @@ -111,6 +108,8 @@ protected virtual void Dispose(bool disposing) _timer.Dispose(); _timer = null; } + + _messenger.Unsubscribe(_subscriptionToken); // Free any other managed objects here. } diff --git a/src/Maple.Core/ViewModels/StatusbarViewModel.cs b/src/Maple.Core/ViewModels/StatusbarViewModel.cs index be1abba..75c4deb 100644 --- a/src/Maple.Core/ViewModels/StatusbarViewModel.cs +++ b/src/Maple.Core/ViewModels/StatusbarViewModel.cs @@ -1,4 +1,5 @@ using System; + using Maple.Domain; using Maple.Localization.Properties; diff --git a/src/Maple.Data/DB/CreateSeedDatabaseIfNotExists.cs b/src/Maple.Data/DB/CreateSeedDatabaseIfNotExists.cs index 141dc9f..f5d37fe 100644 --- a/src/Maple.Data/DB/CreateSeedDatabaseIfNotExists.cs +++ b/src/Maple.Data/DB/CreateSeedDatabaseIfNotExists.cs @@ -182,100 +182,5 @@ private void SeedMediaPlayers(MapleContext context) UpdatedOn = DateTime.UtcNow, }); } - - //private void SeedOptions(TContext context) - //{ - // if (context.Options.Find(1) == null) - // context.Options - // .Add(new OptionModel - // { - // Id = 1, - // Key = "SelectedPlaylist", - // Sequence = 0, - // Type = (int)OptionType.Playlist, - // Value = "1", - // CreatedBy = "SYSTEM", - // UpdatedBy = "SYSTEM", - // CreatedOn = DateTime.UtcNow, - // UpdatedOn = DateTime.UtcNow, - // }); - - // if (context.Options.Find(2) == null) - // context.Options - // .Add(new OptionModel - // { - // Id = 2, - // Key = "SelectedMediaItem", - // Sequence = 10, - // Type = (int)OptionType.MediaItem, - // Value = "", - // CreatedBy = "SYSTEM", - // UpdatedBy = "SYSTEM", - // CreatedOn = DateTime.UtcNow, - // UpdatedOn = DateTime.UtcNow, - // }); - - // if (context.Options.Find(3) == null) - // context.Options - // .Add(new OptionModel - // { - // Id = 3, - // Key = "SelectedMediaPlayer", - // Sequence = 20, - // Type = (int)OptionType.MediaPlayer, - // Value = "1", - // CreatedBy = "SYSTEM", - // UpdatedBy = "SYSTEM", - // CreatedOn = DateTime.UtcNow, - // UpdatedOn = DateTime.UtcNow, - // }); - - // // 4 - - // if (context.Options.Find(5) == null) - // context.Options - // .Add(new OptionModel - // { - // Id = 5, - // Key = "SelectedPrimary", - // Sequence = 40, - // Type = (int)OptionType.ColorProfile, - // Value = "", - // CreatedBy = "SYSTEM", - // UpdatedBy = "SYSTEM", - // CreatedOn = DateTime.UtcNow, - // UpdatedOn = DateTime.UtcNow, - // }); - - // if (context.Options.Find(6) == null) - // context.Options - // .Add(new OptionModel - // { - // Id = 6, - // Key = "SelectedAccent", - // Sequence = 50, - // Type = (int)OptionType.ColorProfile, - // Value = "", - // CreatedBy = "SYSTEM", - // UpdatedBy = "SYSTEM", - // CreatedOn = DateTime.UtcNow, - // UpdatedOn = DateTime.UtcNow, - // }); - - // if (context.Options.Find(7) == null) - // context.Options - // .Add(new OptionModel - // { - // Id = 7, - // Key = "SelectedScene", - // Sequence = 60, - // Type = (int)OptionType.Scene, - // Value = "", - // CreatedBy = "SYSTEM", - // UpdatedBy = "SYSTEM", - // CreatedOn = DateTime.UtcNow, - // UpdatedOn = DateTime.UtcNow, - // }); - //} } } diff --git a/src/Maple.Data/DB/MapleContext.cs b/src/Maple.Data/DB/MapleContext.cs index 5204314..d6761aa 100644 --- a/src/Maple.Data/DB/MapleContext.cs +++ b/src/Maple.Data/DB/MapleContext.cs @@ -22,10 +22,5 @@ protected override void OnModelCreating(DbModelBuilder modelBuilder) ModelConfiguration.Configure(modelBuilder); Database.SetInitializer(new CreateSeedDatabaseIfNotExists(modelBuilder)); } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - } } } diff --git a/src/Maple.Data/Maple.Data.csproj b/src/Maple.Data/Maple.Data.csproj index 5cd9f56..56b1334 100644 --- a/src/Maple.Data/Maple.Data.csproj +++ b/src/Maple.Data/Maple.Data.csproj @@ -39,6 +39,7 @@ 4 AnyCPU false + 7.2 pdbonly @@ -50,11 +51,14 @@ - - - - - + + 7.1.0.5212 + + + + + + diff --git a/src/Maple.Data/Repository/Base/EntityFrameworkReadOnlyRepository.cs b/src/Maple.Data/Repository/Base/EntityFrameworkReadOnlyRepository.cs index 212cb50..674e89d 100644 --- a/src/Maple.Data/Repository/Base/EntityFrameworkReadOnlyRepository.cs +++ b/src/Maple.Data/Repository/Base/EntityFrameworkReadOnlyRepository.cs @@ -14,7 +14,7 @@ public abstract class EntityFrameworkReadOnlyRepository : IReadOnlyRep { protected readonly TContext context; - public EntityFrameworkReadOnlyRepository(TContext context) + protected EntityFrameworkReadOnlyRepository(TContext context) { this.context = context ?? throw new ArgumentNullException(nameof(context)); } @@ -53,7 +53,7 @@ public virtual IEnumerable GetAll( int? take = null) where TEntity : class, IEntity { - return GetQueryable(null, orderBy, includeProperties, skip, take).ToList(); + return GetQueryable(null, orderBy, includeProperties, skip, take).ToList(); } public virtual async Task> GetAllAsync( @@ -63,7 +63,7 @@ public virtual async Task> GetAllAsync( int? take = null) where TEntity : class, IEntity { - return await GetQueryable(null, orderBy, includeProperties, skip, take).ToListAsync(); + return await GetQueryable(null, orderBy, includeProperties, skip, take).ToListAsync(); } public virtual IEnumerable Get( @@ -74,7 +74,7 @@ public virtual IEnumerable Get( int? take = null) where TEntity : class, IEntity { - return GetQueryable(filter, orderBy, includeProperties, skip, take).ToList(); + return GetQueryable(filter, orderBy, includeProperties, skip, take).ToList(); } public virtual async Task> GetAsync( @@ -85,15 +85,15 @@ public virtual async Task> GetAsync( int? take = null) where TEntity : class, IEntity { - return await GetQueryable(filter, orderBy, includeProperties, skip, take).ToListAsync(); + return await GetQueryable(filter, orderBy, includeProperties, skip, take).ToListAsync(); } public virtual TEntity GetOne( Expression> filter = null, - string includeProperties = "") + string includeProperties = default) where TEntity : class, IEntity { - return GetQueryable(filter, null, includeProperties).SingleOrDefault(); + return GetQueryable(filter, null, includeProperties).SingleOrDefault(); } public virtual async Task GetOneAsync( @@ -101,16 +101,16 @@ public virtual async Task GetOneAsync( string includeProperties = null) where TEntity : class, IEntity { - return await GetQueryable(filter, null, includeProperties).SingleOrDefaultAsync(); + return await GetQueryable(filter, null, includeProperties).SingleOrDefaultAsync(); } public virtual TEntity GetFirst( Expression> filter = null, Func, IOrderedQueryable> orderBy = null, - string includeProperties = "") + string includeProperties = default) where TEntity : class, IEntity { - return GetQueryable(filter, orderBy, includeProperties).FirstOrDefault(); + return GetQueryable(filter, orderBy, includeProperties).FirstOrDefault(); } public virtual async Task GetFirstAsync( @@ -119,7 +119,7 @@ public virtual async Task GetFirstAsync( string includeProperties = null) where TEntity : class, IEntity { - return await GetQueryable(filter, orderBy, includeProperties).FirstOrDefaultAsync(); + return await GetQueryable(filter, orderBy, includeProperties).FirstOrDefaultAsync(); } public virtual TEntity GetById(object id) @@ -143,25 +143,25 @@ public Task> GetByIdsAsync(ICollection ids) public virtual int GetCount(Expression> filter = null) where TEntity : class, IEntity { - return GetQueryable(filter).Count(); + return GetQueryable(filter).Count(); } public virtual Task GetCountAsync(Expression> filter = null) where TEntity : class, IEntity { - return GetQueryable(filter).CountAsync(); + return GetQueryable(filter).CountAsync(); } public virtual bool GetExists(Expression> filter = null) where TEntity : class, IEntity { - return GetQueryable(filter).Any(); + return GetQueryable(filter).Any(); } public virtual Task GetExistsAsync(Expression> filter = null) where TEntity : class, IEntity { - return GetQueryable(filter).AnyAsync(); + return GetQueryable(filter).AnyAsync(); } } } \ No newline at end of file diff --git a/src/Maple.Data/Repository/Base/EntityFrameworkRepository.cs b/src/Maple.Data/Repository/Base/EntityFrameworkRepository.cs index 3fc567f..4d0cb6f 100644 --- a/src/Maple.Data/Repository/Base/EntityFrameworkRepository.cs +++ b/src/Maple.Data/Repository/Base/EntityFrameworkRepository.cs @@ -10,7 +10,7 @@ namespace Maple.Data public abstract class EntityFrameworkRepository : EntityFrameworkReadOnlyRepository, IRepository where TContext : DbContext { - public EntityFrameworkRepository(TContext context) + protected EntityFrameworkRepository(TContext context) : base(context) { } diff --git a/src/Maple.Data/Repository/Base/UnitOfWork.cs b/src/Maple.Data/Repository/Base/UnitOfWork.cs index 0bcc7f2..8124c7a 100644 --- a/src/Maple.Data/Repository/Base/UnitOfWork.cs +++ b/src/Maple.Data/Repository/Base/UnitOfWork.cs @@ -58,7 +58,9 @@ private void Dispose(bool disposing) if (disposing) { // Dispose managed resources. +#pragma warning disable S1066 // Collapsible "if" statements should be merged if (_context != null) +#pragma warning restore S1066 // Collapsible "if" statements should be merged { _context.Dispose(); _context = null; diff --git a/src/Maple.Domain/Enums/PlaybackState.cs b/src/Maple.Domain/Enums/PlaybackState.cs index f80b49b..457ef7d 100644 --- a/src/Maple.Domain/Enums/PlaybackState.cs +++ b/src/Maple.Domain/Enums/PlaybackState.cs @@ -5,7 +5,7 @@ namespace Maple.Domain [Flags] public enum PlaybackState { - Stopped = 0, + None = 0, Playing = 1 << 0, Paused = 1 << 1, } diff --git a/src/Maple.Domain/Interfaces/IMediaPlayer.cs b/src/Maple.Domain/Interfaces/IMediaPlayer.cs index 91a4c34..10adfa0 100644 --- a/src/Maple.Domain/Interfaces/IMediaPlayer.cs +++ b/src/Maple.Domain/Interfaces/IMediaPlayer.cs @@ -14,7 +14,7 @@ public interface IMediaPlayer : IDisposable /// Plays the specified item. /// /// The item. - bool Play(IMediaItem item); + bool Play(IMediaItem mediaItem); /// /// Pauses this instance. @@ -43,7 +43,7 @@ public interface IMediaPlayer : IDisposable /// /// The item. /// true if this instance can play the specified item; otherwise, false. - bool CanPlay(IMediaItem item); + bool CanPlay(IMediaItem mediaItem); /// /// Gets or sets the volume. diff --git a/src/Maple.Domain/Interfaces/IRangeObservableCollection.cs b/src/Maple.Domain/Interfaces/IRangeObservableCollection.cs index 22ee68c..b4830be 100644 --- a/src/Maple.Domain/Interfaces/IRangeObservableCollection.cs +++ b/src/Maple.Domain/Interfaces/IRangeObservableCollection.cs @@ -5,7 +5,7 @@ namespace Maple.Domain { - public interface IRangeObservableCollection : IEnumerable, ICollection, INotifyPropertyChanged, IList, INotifyCollectionChanged + public interface IRangeObservableCollection : INotifyPropertyChanged, IList, INotifyCollectionChanged { void AddRange(IEnumerable items); diff --git a/src/Maple.Domain/Maple.Domain.csproj b/src/Maple.Domain/Maple.Domain.csproj index e21a2ac..1410265 100644 --- a/src/Maple.Domain/Maple.Domain.csproj +++ b/src/Maple.Domain/Maple.Domain.csproj @@ -21,6 +21,7 @@ prompt 4 false + 7.2 pdbonly @@ -76,6 +77,10 @@ - + + + 7.1.0.5212 + + \ No newline at end of file diff --git a/src/Maple.Domain/Models/Base/Entity.cs b/src/Maple.Domain/Models/Base/Entity.cs index 5c28e8c..41032a5 100644 --- a/src/Maple.Domain/Models/Base/Entity.cs +++ b/src/Maple.Domain/Models/Base/Entity.cs @@ -36,7 +36,7 @@ public DateTime CreatedOn public byte[] Version { get; set; } [NotMapped] - public bool IsNew => EqualityComparer.Default.Equals(Id, default(T)); + public bool IsNew => EqualityComparer.Default.Equals(Id, default); [NotMapped] public bool IsDeleted { get; set; } diff --git a/src/Maple.Localization/Maple.Localization.csproj b/src/Maple.Localization/Maple.Localization.csproj index 32f1b99..8a75543 100644 --- a/src/Maple.Localization/Maple.Localization.csproj +++ b/src/Maple.Localization/Maple.Localization.csproj @@ -24,6 +24,7 @@ 4 AnyCPU false + 7.2 pdbonly @@ -73,6 +74,10 @@ Resources.Designer.cs - + + + 7.1.0.5212 + + \ No newline at end of file diff --git a/src/Maple.Test/DiagnosticReportTests.cs b/src/Maple.Test/DiagnosticReportTests.cs deleted file mode 100644 index bac4fa6..0000000 --- a/src/Maple.Test/DiagnosticReportTests.cs +++ /dev/null @@ -1,269 +0,0 @@ -using Maple.Core; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Shouldly; - -namespace Maple.Test -{ - [TestClass] - public sealed class DiagnosticReportTests - { - [TestMethod, Ignore("can only be run on system with EN OS")] - public void When_generating_full_report() - { - var report = DiagnosticReport.Generate(); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(1000); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldContain("\r\n|\r\n|System|..."); - report.ShouldContain("\r\n|\r\n|Process|..."); - report.ShouldContain("\r\n|\r\n|Drives|..."); - report.ShouldContain("\r\n|\r\n|Assemblies|..."); - report.ShouldContain("\r\n|\r\n|Networking|..."); - report.ShouldContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - - [TestMethod, Ignore("can only be run on system with EN OS")] - public void When_generating_full_report_with_flag() - { - // ReSharper disable once RedundantArgumentDefaultValue - var report = DiagnosticReport.Generate(DiagnosticReportType.Full); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(1000); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldContain("\r\n|\r\n|System|..."); - report.ShouldContain("\r\n|\r\n|Process|..."); - report.ShouldContain("\r\n|\r\n|Drives|..."); - report.ShouldContain("\r\n|\r\n|Assemblies|..."); - report.ShouldContain("\r\n|\r\n|Networking|..."); - report.ShouldContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - - [TestMethod] - public void When_generating_system_report_with_flag() - { - var report = DiagnosticReport.Generate(DiagnosticReportType.System); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(100); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldContain("\r\n|\r\n|System|..."); - report.ShouldNotContain("\r\n|\r\n|Process|..."); - report.ShouldNotContain("\r\n|\r\n|Drives|..."); - report.ShouldNotContain("\r\n|\r\n|Assemblies|..."); - report.ShouldNotContain("\r\n|\r\n|Networking|..."); - report.ShouldNotContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - - [TestMethod] - public void When_generating_process_report_with_flag() - { - var report = DiagnosticReport.Generate(DiagnosticReportType.Process); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(100); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldNotContain("\r\n|\r\n|System|..."); - report.ShouldContain("\r\n|\r\n|Process|..."); - report.ShouldNotContain("\r\n|\r\n|Drives|..."); - report.ShouldNotContain("\r\n|\r\n|Assemblies|..."); - report.ShouldNotContain("\r\n|\r\n|Networking|..."); - report.ShouldNotContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - - [TestMethod] - public void When_generating_drives_report_with_flag() - { - var report = DiagnosticReport.Generate(DiagnosticReportType.Drives); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(100); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldNotContain("\r\n|\r\n|System|..."); - report.ShouldNotContain("\r\n|\r\n|Process|..."); - report.ShouldContain("\r\n|\r\n|Drives|..."); - report.ShouldNotContain("\r\n|\r\n|Assemblies|..."); - report.ShouldNotContain("\r\n|\r\n|Networking|..."); - report.ShouldNotContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - - [TestMethod] - public void When_generating_assemblies_report_with_flag() - { - var report = DiagnosticReport.Generate(DiagnosticReportType.Assemblies); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(100); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldNotContain("\r\n|\r\n|System|..."); - report.ShouldNotContain("\r\n|\r\n|Process|..."); - report.ShouldNotContain("\r\n|\r\n|Drives|..."); - report.ShouldContain("\r\n|\r\n|Assemblies|..."); - report.ShouldNotContain("\r\n|\r\n|Networking|..."); - report.ShouldNotContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - - [TestMethod, Ignore("can only be run on system with EN OS")] - public void When_generating_networking_report_with_flag() - { - var report = DiagnosticReport.Generate(DiagnosticReportType.Networking); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(100); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldNotContain("\r\n|\r\n|System|..."); - report.ShouldNotContain("\r\n|\r\n|Process|..."); - report.ShouldNotContain("\r\n|\r\n|Drives|..."); - report.ShouldNotContain("\r\n|\r\n|Assemblies|..."); - report.ShouldContain("\r\n|\r\n|Networking|..."); - report.ShouldContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - - [TestMethod] - public void When_generating_system_and_process_report() - { - var flags = DiagnosticReportType.System | DiagnosticReportType.Process; - var report = DiagnosticReport.Generate(flags); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(100); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldContain("\r\n|\r\n|System|..."); - report.ShouldContain("\r\n|\r\n|Process|..."); - report.ShouldNotContain("\r\n|\r\n|Drives|..."); - report.ShouldNotContain("\r\n|\r\n|Assemblies|..."); - report.ShouldNotContain("\r\n|\r\n|Networking|..."); - report.ShouldNotContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - - [TestMethod] - public void When_generating_system_and_drives_report() - { - var flags = DiagnosticReportType.System | DiagnosticReportType.Drives; - var report = DiagnosticReport.Generate(flags); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(100); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldContain("\r\n|\r\n|System|..."); - report.ShouldNotContain("\r\n|\r\n|Process|..."); - report.ShouldContain("\r\n|\r\n|Drives|..."); - report.ShouldNotContain("\r\n|\r\n|Assemblies|..."); - report.ShouldNotContain("\r\n|\r\n|Networking|..."); - report.ShouldNotContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - - [TestMethod] - public void When_generating_system_and_assemblies_report() - { - var flags = DiagnosticReportType.System | DiagnosticReportType.Assemblies; - var report = DiagnosticReport.Generate(flags); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(100); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldContain("\r\n|\r\n|System|..."); - report.ShouldNotContain("\r\n|\r\n|Process|..."); - report.ShouldNotContain("\r\n|\r\n|Drives|..."); - report.ShouldContain("\r\n|\r\n|Assemblies|..."); - report.ShouldNotContain("\r\n|\r\n|Networking|..."); - report.ShouldNotContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - - [TestMethod, Ignore("can only be run on system with EN OS")] - public void When_generating_system_and_networking_report() - { - var flags = DiagnosticReportType.System | DiagnosticReportType.Networking; - var report = DiagnosticReport.Generate(flags); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(100); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldContain("\r\n|\r\n|System|..."); - report.ShouldNotContain("\r\n|\r\n|Process|..."); - report.ShouldNotContain("\r\n|\r\n|Drives|..."); - report.ShouldNotContain("\r\n|\r\n|Assemblies|..."); - report.ShouldContain("\r\n|\r\n|Networking|..."); - report.ShouldContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - - - [TestMethod, Ignore("can only be run on system with EN OS")] - public void When_generating_system_and_process_and_drives_and_assemblies_and_environment_variables_and_networking_report() - { - var flags = DiagnosticReportType.System - | DiagnosticReportType.Process - | DiagnosticReportType.Drives - | DiagnosticReportType.Assemblies - | DiagnosticReportType.Networking; - - var report = DiagnosticReport.Generate(flags); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(1000); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldContain("\r\n|\r\n|System|..."); - report.ShouldContain("\r\n|\r\n|Process|..."); - report.ShouldContain("\r\n|\r\n|Drives|..."); - report.ShouldContain("\r\n|\r\n|Assemblies|..."); - report.ShouldContain("\r\n|\r\n|Networking|..."); - report.ShouldContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - - [TestMethod, Ignore("can only be run on system with EN OS")] - public void When_generating_process_and_assemblies_and_networking_report() - { - var flags = DiagnosticReportType.Process - | DiagnosticReportType.Assemblies - | DiagnosticReportType.Networking; - - var report = DiagnosticReport.Generate(flags); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(500); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldNotContain("\r\n|\r\n|System|..."); - report.ShouldContain("\r\n|\r\n|Process|..."); - report.ShouldNotContain("\r\n|\r\n|Drives|..."); - report.ShouldContain("\r\n|\r\n|Assemblies|..."); - report.ShouldContain("\r\n|\r\n|Networking|..."); - report.ShouldContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - - [TestMethod, Ignore("can only be run on system with EN OS")] - public void When_generating_process_and_assemblies_and_networking_and_full_report() - { - var flags = DiagnosticReportType.Process - | DiagnosticReportType.Assemblies - | DiagnosticReportType.Networking - | DiagnosticReportType.Full; - - var report = DiagnosticReport.Generate(flags); - report.ShouldNotBeNull(); - report.Length.ShouldBeGreaterThan(1000); - - report.ShouldStartWith("/\r\n|Diagnostic Report generated at:"); - report.ShouldContain("\r\n|\r\n|System|..."); - report.ShouldContain("\r\n|\r\n|Process|..."); - report.ShouldContain("\r\n|\r\n|Drives|..."); - report.ShouldContain("\r\n|\r\n|Assemblies|..."); - report.ShouldContain("\r\n|\r\n|Networking|..."); - report.ShouldContain("|\r\n|\t. Windows IP Configuration\r\n|"); - report.ShouldEndWith("\\"); - } - } -} \ No newline at end of file diff --git a/src/Maple.Test/DynamicDictionaryTests.cs b/src/Maple.Test/DynamicDictionaryTests.cs deleted file mode 100644 index ac76e9a..0000000 --- a/src/Maple.Test/DynamicDictionaryTests.cs +++ /dev/null @@ -1,267 +0,0 @@ -using System; -using System.Collections.Generic; -using Maple.Core; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Shouldly; - -namespace Maple.Test -{ - [TestClass] - public sealed class DynamicDictionaryTests - { - [TestMethod] - public void When_testing_as_concrete_type() - { - var dic = new DynamicDictionary(); - dic.Count.ShouldBe(0); - - dic["A"] = "A"; - dic["B"] = "B"; - dic["C"] = "C"; - dic["D"] = 1; - - dic.Count.ShouldBe(4); - dic["A"].ShouldBe("A"); - dic["a"].ShouldBe("A"); - dic["B"].ShouldBe("B"); - dic["b"].ShouldBe("B"); - dic["C"].ShouldBe("C"); - dic["c"].ShouldBe("C"); - dic["D"].ShouldBe(1); - dic["d"].ShouldBe(1); - - dic.Keys.ShouldBe(new[] { "A", "B", "C", "D" }); - dic.Values.ShouldBe(new object[] { "A", "B", "C", 1 }); - - dic["non-existent"].ShouldBeNull(); - } - - [TestMethod] - public void When_testing_as_dynamic_type() - { - dynamic dic = new DynamicDictionary(); - ((int)dic.Count).ShouldBe(0); - - dic["A"] = "A"; - dic["B"] = "B"; - dic["C"] = "C"; - dic["D"] = 1; - -#pragma warning disable IDE0039 // Use local function - Func someFunc = () => 1234; -#pragma warning restore IDE0039 // Use local function - dic.action = someFunc; - - ((int)dic.Count).ShouldBe(5); - ((string)dic["A"]).ShouldBe("A"); - ((string)dic["a"]).ShouldBe("A"); - ((string)dic["B"]).ShouldBe("B"); - ((string)dic["b"]).ShouldBe("B"); - ((string)dic["C"]).ShouldBe("C"); - ((string)dic["c"]).ShouldBe("C"); - ((int)dic["D"]).ShouldBe(1); - ((int)dic["d"]).ShouldBe(1); - - ((int)dic.action()).ShouldBe(1234); - ((int)dic.ACTION()).ShouldBe(1234); - - ((string)dic.A).ShouldBe("A"); - ((string)dic.a).ShouldBe("A"); - ((int)dic.D).ShouldBe(1); - ((int)dic.d).ShouldBe(1); - - ((ICollection)dic.Keys).ShouldBe(new[] { "A", "B", "C", "D", "action" }); - ((ICollection)dic.Values).ShouldBe(new object[] { "A", "B", "C", 1, someFunc }); - - ((string)dic["non-existent"]).ShouldBeNull(); - - dic.foo = "foo"; - ((string)dic["foo"]).ShouldBe("foo"); - ((string)dic["Foo"]).ShouldBe("foo"); - } - - [TestMethod] - public void When_testing_case_sensitivity() - { - var caseSensetiveDic = new DynamicDictionary(false) - { - ["A"] = 1, - ["Id"] = 66 - }; - - caseSensetiveDic["A"].ShouldBe(1); - caseSensetiveDic["Id"].ShouldBe(66); - - caseSensetiveDic["a"].ShouldBeNull(); - caseSensetiveDic["ID"].ShouldBeNull(); - caseSensetiveDic["iD"].ShouldBeNull(); - - dynamic dynCaseSensetiveDic = caseSensetiveDic; - dynCaseSensetiveDic.A = "sample"; - ((string)dynCaseSensetiveDic.A).ShouldBe("sample"); - ((int)dynCaseSensetiveDic.Id).ShouldBe(66); - - ((string)dynCaseSensetiveDic.a).ShouldBeNull(); - ((string)dynCaseSensetiveDic.ID).ShouldBeNull(); - - var caseInSensetiveDic = new DynamicDictionary() - { - ["A"] = 1, - ["Id"] = 66 - }; - - caseInSensetiveDic["A"].ShouldBe(1); - caseInSensetiveDic["Id"].ShouldBe(66); - - caseInSensetiveDic["a"].ShouldBe(1); - caseInSensetiveDic["ID"].ShouldBe(66); - caseInSensetiveDic["iD"].ShouldBe(66); - - dynamic dynCaseInSensetiveDic = caseInSensetiveDic; - dynCaseInSensetiveDic.A = "sample"; - ((string)dynCaseInSensetiveDic.A).ShouldBe("sample"); - ((string)dynCaseInSensetiveDic.a).ShouldBe("sample"); - - ((int)dynCaseInSensetiveDic.Id).ShouldBe(66); - ((int)dynCaseInSensetiveDic.ID).ShouldBe(66); - ((int)dynCaseInSensetiveDic.id).ShouldBe(66); - } - - [TestMethod] - public void When_enumerating_as_dynamic() - { - dynamic dic = new DynamicDictionary(); - ((int)dic.Count).ShouldBe(0); - - dic["A"] = "1"; - dic["B"] = "2"; - dic["C"] = "3"; - dic["D"] = 66; - - foreach (KeyValuePair pair in dic) - { - pair.Key.ShouldBeOfType(); - - if (pair.Key == "A") - { - pair.Value.ShouldBeOfType(); - pair.Value.ShouldBe("1"); - } - - if (pair.Key == "B") - { - pair.Value.ShouldBeOfType(); - pair.Value.ShouldBe("2"); - } - - if (pair.Key == "C") - { - pair.Value.ShouldBeOfType(); - pair.Value.ShouldBe("3"); - } - - if (pair.Key == "D") - { - pair.Value.ShouldBeOfType(); - pair.Value.ShouldBe(66); - } - } - } - - [TestMethod] - public void When_enumerating_as_original_type() - { - var dic = new DynamicDictionary(); - dic.Count.ShouldBe(0); - - dic["A"] = "1"; - dic["B"] = "2"; - dic["C"] = "3"; - dic["D"] = 66; - - foreach (var pair in dic) - { - pair.Key.ShouldBeOfType(); - - if (pair.Key == "A") - { - pair.Value.ShouldBeOfType(); - pair.Value.ShouldBe("1"); - } - - if (pair.Key == "B") - { - pair.Value.ShouldBeOfType(); - pair.Value.ShouldBe("2"); - } - - if (pair.Key == "C") - { - pair.Value.ShouldBeOfType(); - pair.Value.ShouldBe("3"); - } - - if (pair.Key == "D") - { - pair.Value.ShouldBeOfType(); - pair.Value.ShouldBe(66); - } - } - } - - [TestMethod] - public void When_getting_a_model_as_dynamic_dictionary() - { - var model = new Child { Name = "Foo", Age = 10 }; - var dicWithInherittedProp = model.ToDynamic(); - - dicWithInherittedProp.ShouldNotBeNull(); - dicWithInherittedProp.Count.ShouldBe(3); - dicWithInherittedProp["OriginalName"].ShouldBe("PaPa"); - dicWithInherittedProp["Name"].ShouldBe("Foo"); - dicWithInherittedProp["Age"].ShouldBe(10); - - var dicWithDeclaredProp = model.ToDynamic(false); - - dicWithDeclaredProp.ShouldNotBeNull(); - dicWithDeclaredProp.Count.ShouldBe(2); - dicWithDeclaredProp["OriginalName"].ShouldBeNull(); - dicWithDeclaredProp["Name"].ShouldBe("Foo"); - dicWithDeclaredProp["Age"].ShouldBe(10); - } - - [TestMethod] - public void When_getting_a_model_as_dynamic() - { - var model = new Child { Name = "Foo", Age = 10 }; - dynamic dicWithInherittedProp = model.ToDynamic(); - - ((DynamicDictionary)dicWithInherittedProp).ShouldNotBeNull(); - ((DynamicDictionary)dicWithInherittedProp).Count.ShouldBe(3); - - ((string)dicWithInherittedProp["OriginalName"]).ShouldBe("PaPa"); - ((string)dicWithInherittedProp["Name"]).ShouldBe("Foo"); - ((int)dicWithInherittedProp["Age"]).ShouldBe(10); - - dynamic dicWithDeclaredProp = model.ToDynamic(false); - - ((DynamicDictionary)dicWithDeclaredProp).ShouldNotBeNull(); - ((DynamicDictionary)dicWithDeclaredProp).Count.ShouldBe(2); - - ((string)dicWithDeclaredProp["OriginalName"]).ShouldBeNull(); - ((string)dicWithDeclaredProp["Name"]).ShouldBe("Foo"); - ((int)dicWithDeclaredProp["Age"]).ShouldBe(10); - } - - private class Base - { - public string OriginalName => "PaPa"; - } - - private sealed class Child : Base - { - public string Name { get; set; } - public int Age { get; set; } - } - } -} diff --git a/src/Maple.Test/Maple.Test.csproj b/src/Maple.Test/Maple.Test.csproj index 152c684..8ed122e 100644 --- a/src/Maple.Test/Maple.Test.csproj +++ b/src/Maple.Test/Maple.Test.csproj @@ -48,7 +48,6 @@ Properties\SharedAssemblyInfo.cs - @@ -59,7 +58,6 @@ - @@ -126,6 +124,9 @@ 2.8.3 + + 7.1.0.5212 + diff --git a/src/Maple.Test/TestUtils/ContainerContextExtensions.cs b/src/Maple.Test/TestUtils/ContainerContextExtensions.cs index 588d474..4ac9339 100644 --- a/src/Maple.Test/TestUtils/ContainerContextExtensions.cs +++ b/src/Maple.Test/TestUtils/ContainerContextExtensions.cs @@ -1,6 +1,9 @@ using DryIoc; + using Maple.Core; +using Maple.Data; using Maple.Domain; + using NSubstitute; namespace Maple.Test @@ -92,7 +95,7 @@ public static IDialogViewModel CreateDialogViewModel() return Substitute.For(); } - public static IMediaRepository CreateRepository() + public static MapleRepository CreateRepository() { return Substitute.For(); } diff --git a/src/Maple.Youtube/YoutubeApi.cs b/src/Maple.Youtube/YoutubeApi.cs index 09b9b9b..a900048 100644 --- a/src/Maple.Youtube/YoutubeApi.cs +++ b/src/Maple.Youtube/YoutubeApi.cs @@ -5,11 +5,13 @@ using System.Threading.Tasks; using System.Web; using System.Xml; + using Google.Apis.Auth.OAuth2; using Google.Apis.Services; using Google.Apis.Util.Store; using Google.Apis.YouTube.v3; using Google.Apis.YouTube.v3.Data; + using Maple.Domain; using Maple.Localization.Properties; @@ -17,17 +19,17 @@ namespace Maple.Youtube { public class YoutubeApi : IYoutubeApi { +#pragma warning disable S1075 // URIs should not be hardcoded private const string _videoBaseUrl = @"https://www.youtube.com/watch?v="; private const string _playListBaseUrl = @"https://www.youtube.com/playlist?list="; +#pragma warning restore S1075 // URIs should not be hardcoded private volatile YouTubeService _service; private readonly ILoggingService _log; - private readonly object _syncRoot; public YoutubeApi(ILoggingService log) { _log = log ?? throw new ArgumentNullException(nameof(log), $"{nameof(log)} {Resources.IsRequired}"); - _syncRoot = new object(); } private async Task GetService() @@ -109,7 +111,7 @@ public async Task CreatePlaylist(PlaylistModel playlist, bool publicPlaylist = t }, Status = new PlaylistStatus { - PrivacyStatus = publicPlaylist == true ? "public" : "private" + PrivacyStatus = publicPlaylist ? "public" : "private" } }; newPlaylist = await youtubeService.Playlists.Insert(newPlaylist, "snippet,status") @@ -129,7 +131,7 @@ public async Task CreatePlaylist(PlaylistModel playlist, bool publicPlaylist = t }; newVideo.Snippet.ResourceId.Kind = "youtube#video"; newVideo.Snippet.ResourceId.VideoId = GetVideoId(item); - newVideo = await youtubeService.PlaylistItems.Insert(newVideo, "snippet") + await youtubeService.PlaylistItems.Insert(newVideo, "snippet") .ExecuteAsync() .ConfigureAwait(false); } diff --git a/src/Maple/DependencyInjectionFactory.cs b/src/Maple/DependencyInjectionFactory.cs index 9bce2d8..22ea503 100644 --- a/src/Maple/DependencyInjectionFactory.cs +++ b/src/Maple/DependencyInjectionFactory.cs @@ -89,8 +89,7 @@ void RegisterServices() c.Register(Reuse.Singleton); c.Register(Reuse.Singleton); - c.Register(setup: Setup.DecoratorWith(order: 1)); - c.Register(setup: Setup.DecoratorWith(order: 2)); + c.Register(setup: Setup.DecoratorWith(order: 1)); } void RegisterValidation() diff --git a/src/Maple/UI/MarkupExtensions/TranslationExtension.cs b/src/Maple/UI/MarkupExtensions/TranslationExtension.cs index 847c28b..f536d1e 100644 --- a/src/Maple/UI/MarkupExtensions/TranslationExtension.cs +++ b/src/Maple/UI/MarkupExtensions/TranslationExtension.cs @@ -74,7 +74,7 @@ private object ProvideValue(IServiceProvider serviceProvider, ILocalizationServi { var binding = new Binding("Value") { - Source = new LocalizationDTO(manager, Key, ToUpper) + Source = new LocalizationDto(manager, Key, ToUpper) }; return binding.ProvideValue(serviceProvider); From d646ce470332e1a8a33d69d4ba6e47d00bd09034 Mon Sep 17 00:00:00 2001 From: Insire Date: Sun, 6 May 2018 19:03:25 +0200 Subject: [PATCH 15/16] missed 2 project updates --- src/Maple.Youtube/Maple.Youtube.csproj | 3 +++ src/Maple/Maple.csproj | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/Maple.Youtube/Maple.Youtube.csproj b/src/Maple.Youtube/Maple.Youtube.csproj index 5321469..c3cc411 100644 --- a/src/Maple.Youtube/Maple.Youtube.csproj +++ b/src/Maple.Youtube/Maple.Youtube.csproj @@ -37,6 +37,9 @@ 1.32.0.1079 + + 7.1.0.5212 + 0.10.11 diff --git a/src/Maple/Maple.csproj b/src/Maple/Maple.csproj index 2af8155..6c35a79 100644 --- a/src/Maple/Maple.csproj +++ b/src/Maple/Maple.csproj @@ -72,6 +72,9 @@ + + 7.1.0.5212 + 1.7.8 From 8dd398fe81482e912880c711a9f4e9b1b95b0205 Mon Sep 17 00:00:00 2001 From: Insire Date: Sun, 6 May 2018 19:06:42 +0200 Subject: [PATCH 16/16] updated some nuget packages --- src/Maple.Youtube/Maple.Youtube.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Maple.Youtube/Maple.Youtube.csproj b/src/Maple.Youtube/Maple.Youtube.csproj index c3cc411..3fad06a 100644 --- a/src/Maple.Youtube/Maple.Youtube.csproj +++ b/src/Maple.Youtube/Maple.Youtube.csproj @@ -34,9 +34,9 @@ - 1.32.0.1079 + 1.33.0.1215 - + 7.1.0.5212