// // Licensed under the MIT License. See LICENSE file in the project root for full license information. // namespace MUnique.OpenMU.Persistence.InMemory; using System.Threading; using MUnique.OpenMU.DataModel.Configuration; using MUnique.OpenMU.Interfaces; using MUnique.OpenMU.PlugIns; using Nito.Disposables; /// /// A context provider which uses in-memory repositories to hold its data, e.g. for testing or demo purposes. /// Changes in one context directly have effect in other contexts! Calling SaveChanges or not doesn't matter. /// public class InMemoryPersistenceContextProvider : IMigratableDatabaseContextProvider { private InMemoryRepositoryProvider _repositoryProvider = new(); /// /// Initializes a new instance of the class. /// /// The change publisher. public InMemoryPersistenceContextProvider(IConfigurationChangePublisher? changePublisher = null) { this.ChangePublisher = changePublisher; } /// public IRepositoryProvider RepositoryProvider => this._repositoryProvider; /// /// Gets or sets the publisher for configuration changes. /// public IConfigurationChangePublisher? ChangePublisher { get; set; } /// public IContext CreateNewContext() { var context = new InMemoryContext(this._repositoryProvider); this.AttachChangePublisher(context, typeof(PlugInConfiguration)); return context; } /// public IContext CreateNewContext(GameConfiguration gameConfiguration) { var context = new InMemoryContext(this._repositoryProvider); this.AttachChangePublisher(context, typeof(PlugInConfiguration)); return context; } /// public IContext CreateNewTradeContext() { return new InMemoryContext(this._repositoryProvider); } /// public IPlayerContext CreateNewPlayerContext(GameConfiguration gameConfiguration) { return new PlayerInMemoryContext(this._repositoryProvider); } /// public IConfigurationContext CreateNewConfigurationContext() { return new ConfigurationInMemoryContext(this._repositoryProvider); } /// public IFriendServerContext CreateNewFriendServerContext() { return new FriendServerInMemoryContext(this._repositoryProvider); } /// public IGuildServerContext CreateNewGuildContext() { return new GuildServerInMemoryContext(this._repositoryProvider); } /// public IContext CreateNewTypedContext(Type editType, bool useCache, GameConfiguration? gameConfiguration = null) { var context = new InMemoryContext(this._repositoryProvider); this.AttachChangePublisher(context, editType); return context; } /// public Task DatabaseExistsAsync(CancellationToken cancellationToken) { return Task.FromResult(true); } /// public Task IsDatabaseUpToDateAsync(CancellationToken cancellationToken) { return Task.FromResult(true); } /// public Task ApplyAllPendingUpdatesAsync() { // we don't need to do anything. return Task.CompletedTask; } /// public Task WaitForUpdatedDatabaseAsync(CancellationToken cancellationToken = default) { return Task.CompletedTask; } /// public Task CanConnectToDatabaseAsync(CancellationToken cancellationToken) { return Task.FromResult(true); } /// public Task ShouldDoAutoSchemaUpdateAsync(CancellationToken cancellationToken = default) { return Task.FromResult(true); } /// public Task ReCreateDatabaseAsync(bool dropExistingDatabase = true) { this._repositoryProvider = new(); return Task.FromResult(new Disposable(() => { })); } /// public void ResetCache() { // do nothing here } private void AttachChangePublisher(InMemoryContext context, Type editType) { if (this.ChangePublisher is { } changePublisher) { #pragma warning disable VSTHRD100 async void OnContextOnSavedChanges(object? o, EventArgs e) #pragma warning restore VSTHRD100 { await this.PublishConfigurationChangesAsync(context, changePublisher, editType).ConfigureAwait(false); } context.SavedChanges += OnContextOnSavedChanges; } } private async ValueTask PublishConfigurationChangesAsync(InMemoryContext context, IConfigurationChangePublisher changePublisher, Type editType) { try { foreach (var obj in await context.GetAsync(editType, default).ConfigureAwait(false)) { await changePublisher.ConfigurationChangedAsync(editType, obj.GetId(), obj).ConfigureAwait(false); } } catch { // ignore all errors. } } }