// // Licensed under the MIT License. See LICENSE file in the project root for full license information. // namespace MUnique.OpenMU.Persistence.EntityFramework; using Microsoft.Extensions.Logging; using MUnique.OpenMU.DataModel; using MUnique.OpenMU.DataModel.Configuration; using MUnique.OpenMU.Interfaces; /// /// This provider holds two other repository providers: /// One which provides repositories which actually load the data from the database, /// and another one which returns repositories with cached data, based on the /// loaded GameConfiguration. The CacheAwareRepositoryProvider first tries to retrieve /// a repository for the cached data. If none is found, it takes the other. /// internal class CacheAwareRepositoryProvider : ICacheAwareRepositoryProvider, IContextAwareRepositoryProvider { private readonly ILoggerFactory _loggerFactory; private readonly IRepositoryProvider _nonCachingRepositoryProvider; private CachingRepositoryProvider _cachingRepositoryProvider; /// /// Initializes a new instance of the class. /// /// The logger factory. /// The configuration change listener. public CacheAwareRepositoryProvider(ILoggerFactory loggerFactory, IConfigurationChangeListener? configurationChangeListener) { this._loggerFactory = loggerFactory; this._cachingRepositoryProvider = new CachingRepositoryProvider(loggerFactory, this); this._nonCachingRepositoryProvider = new NonCachingRepositoryProvider(loggerFactory, this, configurationChangeListener, this.ContextStack); } /// public IContextStack ContextStack { get; } = new ContextStack(); /// public IRepository? GetRepository(Type objectType) { if (this.ContextStack.GetCurrentContext() is EntityFrameworkContextBase { Context: ITypedContext editContext } && editContext.IsIncluded(objectType)) { return this._nonCachingRepositoryProvider.GetRepository(objectType); } return this._cachingRepositoryProvider.GetRepository(objectType) ?? this._nonCachingRepositoryProvider.GetRepository(objectType); } /// public IRepository? GetRepository() where T : class { if (this.ContextStack.GetCurrentContext() is EntityFrameworkContextBase { Context: ITypedContext editContext } && (editContext.IsIncluded(typeof(T)) || editContext.IsIncluded(typeof(T).BaseType!))) { return this._nonCachingRepositoryProvider.GetRepository(); } return this._cachingRepositoryProvider.GetRepository() ?? this._nonCachingRepositoryProvider.GetRepository(); } /// public TRepository? GetRepository() where T : class where TRepository : IRepository { if (this.ContextStack.GetCurrentContext() is EntityFrameworkContextBase { Context: ITypedContext editContext } && (editContext.IsIncluded(typeof(T)) || editContext.IsIncluded(typeof(T).BaseType!))) { return this._nonCachingRepositoryProvider.GetRepository(); } return this._cachingRepositoryProvider.GetRepository() ?? this._nonCachingRepositoryProvider.GetRepository(); } /// public void EnsureCachesForCurrentGameConfiguration() { this._cachingRepositoryProvider.EnsureCachesForCurrentGameConfiguration(); } /// public void ResetCache() { this._cachingRepositoryProvider = new CachingRepositoryProvider(this._loggerFactory, this); } /// public async ValueTask UpdateCachedInstanceAsync(object changedInstance) { if (this._cachingRepositoryProvider.GetRepository(changedInstance.GetType().BaseType ?? changedInstance.GetType()) is IConfigurationTypeRepository repository) { repository.UpdateCachedInstances(changedInstance); } else { // not all types have an own repository. var gameConfigRepo = this._cachingRepositoryProvider.GetRepository(); if (gameConfigRepo is null) { return; } foreach (var config in await gameConfigRepo.GetAllAsync().ConfigureAwait(false)) { var obj = config.GetObjectOfConfig(changedInstance) as IAssignable; obj?.AssignValuesOf(changedInstance, config); } } } }