Files
AdamuSw/src/PlugIns/StrategyPlugInProvider.cs
2026-07-14 19:00:35 +03:00

108 lines
3.6 KiB
C#

// <copyright file="StrategyPlugInProvider.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.PlugIns;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Logging;
/// <summary>
/// The implementation for the <see cref="IStrategyPlugInProvider{TKey,TPlugIn}"/> which provides plugins by their key.
/// </summary>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <typeparam name="TPlugIn">The type of the plugin.</typeparam>
/// <seealso cref="MUnique.OpenMU.PlugIns.IStrategyPlugInProvider{TKey, TPlugIn}" />
/// <seealso cref="IPlugInContainer{TPlugIn}" />
public class StrategyPlugInProvider<TKey, TPlugIn> : PlugInContainerBase<TPlugIn>, IStrategyPlugInProvider<TKey, TPlugIn>
where TPlugIn : class, IStrategyPlugIn<TKey>
where TKey : notnull
{
private readonly IDictionary<TKey, TPlugIn> _effectiveStrategies = new Dictionary<TKey, TPlugIn>();
/// <summary>
/// Initializes a new instance of the <see cref="StrategyPlugInProvider{TKey, TPlugIn}" /> class.
/// </summary>
/// <param name="manager">The plugin manager that manages this instance.</param>
/// <param name="loggerFactory">The logger factory.</param>
public StrategyPlugInProvider(PlugInManager manager, ILoggerFactory loggerFactory)
: base(manager)
{
this.Logger = loggerFactory.CreateLogger(this.GetType());
}
/// <inheritdoc />
public IEnumerable<TPlugIn> AvailableStrategies
{
get
{
using var l = this.Lock.ReaderLock();
return this._effectiveStrategies.Values.ToList();
}
}
/// <summary>
/// Gets the logger.
/// </summary>
/// <value>
/// The logger.
/// </value>
protected ILogger Logger { get; }
/// <inheritdoc />
public TPlugIn? this[TKey key]
{
get
{
using var l = this.Lock.ReaderLock();
if (this.TryGetPlugIn(key, out var plugIn))
{
return plugIn;
}
return default;
}
}
/// <summary>
/// Tries the get the plug in with the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="plugIn">The plugin.</param>
/// <returns><c>True</c>, if the plugin has been found and returned; Otherwise, <c>false</c>.</returns>
protected bool TryGetPlugIn(TKey key, [MaybeNullWhen(false)] out TPlugIn plugIn) => this._effectiveStrategies.TryGetValue(key, out plugIn);
/// <inheritdoc />
protected override void ActivatePlugIn(TPlugIn plugIn)
{
base.ActivatePlugIn(plugIn);
if (this._effectiveStrategies.TryGetValue(plugIn.Key, out var registeredPlugIn))
{
this.Logger.LogWarning($"Plugin {registeredPlugIn} with key {plugIn.Key} was already registered and is active. Plugin {plugIn} will not be effective.");
}
else
{
this.SetEffectivePlugin(plugIn);
}
}
/// <inheritdoc />
protected override void DeactivatePlugIn(TPlugIn plugIn)
{
base.DeactivatePlugIn(plugIn);
if (this._effectiveStrategies.TryGetValue(plugIn.Key, out var effective) && effective == plugIn)
{
this._effectiveStrategies.Remove(plugIn.Key);
}
}
/// <summary>
/// Sets the effective plugin.
/// </summary>
/// <param name="plugIn">The plugin.</param>
protected void SetEffectivePlugin(TPlugIn plugIn)
{
this._effectiveStrategies.Remove(plugIn.Key);
this._effectiveStrategies.Add(plugIn.Key, plugIn);
}
}