Dashboard/Dashboard.Common/Pal/DeviceContext.cs

99 lines
2.9 KiB
C#

using Dashboard.Collections;
namespace Dashboard.Pal
{
public abstract class DeviceContext : IContextBase<DeviceContext, IDeviceContextExtension>
{
private readonly TypeDictionary<IDeviceContextExtension> _extensions =
new TypeDictionary<IDeviceContextExtension>(true);
private readonly TypeDictionary<IDeviceContextExtension, Func<IDeviceContextExtension>> _preloadedExtensions =
new TypeDictionary<IDeviceContextExtension, Func<IDeviceContextExtension>>(true);
public abstract string DriverName { get; }
public abstract string DriverVendor { get; }
public abstract Version DriverVersion { get; }
public bool IsDisposed { get; private set; }
/// <summary>
/// Optional debugging object for your pleasure.
/// </summary>
public IContextDebugger? Debugger { get; set; }
~DeviceContext()
{
Dispose(false);
}
public virtual void Begin() { }
// public abstract void Paint(object renderbuffer);
public virtual void End() { }
public bool IsExtensionAvailable<T>() where T : IDeviceContextExtension
{
return _extensions.Contains<T>() || _preloadedExtensions.Contains<T>();
}
public bool ExtensionPreload<T>() where T : IDeviceContextExtension, new()
{
return _preloadedExtensions.Add<T>(() => new T());
}
public T ExtensionRequire<T>() where T : IDeviceContextExtension, new()
{
T? extension = default;
if (_extensions.TryGet(out extension))
return extension;
lock (_extensions)
{
if (_extensions.TryGet(out extension))
return extension;
if (_preloadedExtensions.Remove<T>(out Func<IDeviceContextExtension>? loader))
{
extension = (T)loader!();
}
else
{
extension = new T();
}
_extensions.Add(extension);
extension.Require(this);
}
return extension;
}
/// <summary>
/// Implement your dispose in this function.
/// </summary>
/// <param name="isDisposing">True if disposing, false otherwise.</param>
protected virtual void Dispose(bool isDisposing)
{
if (!isDisposing) return;
foreach (IDeviceContextExtension extension in _extensions)
{
extension.Dispose();
}
GC.SuppressFinalize(this);
}
private void InvokeDispose(bool isDisposing)
{
if (IsDisposed) return;
IsDisposed = true;
Dispose(isDisposing);
}
public void Dispose() => InvokeDispose(true);
}
}