//
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//
namespace MUnique.OpenMU.Persistence;
using System.Collections;
using System.Diagnostics;
using System.Threading;
using Microsoft.Extensions.Logging;
using Nito.AsyncEx;
///
/// Provider which provides the latest and it's containing
/// child objects.
///
/// The type of the owner.
///
/// Approach: One context for each composition root type. When child data is going to be edited, the whole type
/// should be loaded.
///
public abstract class DataSourceBase : IDataSource
where TOwner : class
{
private readonly ILogger> _logger;
private readonly AsyncLock _loadLock = new();
private IContext? _context;
private TOwner? _owner;
private IDictionary? _subObjects;
///
/// Initializes a new instance of the class.
///
/// The logger.
/// The persistence context provider.
protected DataSourceBase(ILogger> logger, IPersistenceContextProvider persistenceContextProvider)
{
this._logger = logger;
this.ContextProvider = persistenceContextProvider;
}
///
/// Gets the mapping of a to their of the .
///
protected abstract IReadOnlyDictionary> TypeToEnumerables { get; }
///
/// Gets the which can be used to create new contexts.
///
protected IPersistenceContextProvider ContextProvider { get; }
private TOwner Owner => this._owner ?? throw new InvalidOperationException("owner is not loaded.");
private IDictionary SubObjects => this._subObjects ??= this.BuildDictionary();
///
public bool IsSupporting(Type type)
{
return this.TypeToEnumerables.ContainsKey(type);
}
///
async ValueTask IDataSource.GetOwnerAsync(Guid ownerId, CancellationToken cancellationToken)
{
return (TOwner)(await this.GetOwnerAsync(ownerId, cancellationToken).ConfigureAwait(false));
}
///
public async ValueTask GetContextAsync(CancellationToken cancellationToken)
{
return this._context ??= await this.CreateNewContextAsync().ConfigureAwait(false);
}
///
public async ValueTask