Vanara/Windows.Shell.Common/TaskBar/ExtenderProviderBase.cs

126 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Linq;
using System.Runtime.CompilerServices;
namespace Vanara.Windows
{
/// <summary>A generic base to implement <see cref="IExtenderProvider"/> for a single extender type.</summary>
/// <typeparam name="TExtend">The type of the type that can be extended.</typeparam>
public abstract class ExtenderProviderBase<TExtend> : Component, IExtenderProvider, ISupportInitialize where TExtend : Component
{
/// <summary>A dictionary that holds a property bag for each extended type.</summary>
protected readonly Dictionary<TExtend, Dictionary<string, object>> propHash = new();
/// <summary>Initializes a new instance of the <see cref="ExtenderProviderBase{TExtend}"/> class.</summary>
protected ExtenderProviderBase() { }
/// <summary>Initializes a new instance of the <see cref="ExtenderProviderBase{TExtend}"/> class.</summary>
/// <param name="parent">The parent.</param>
protected ExtenderProviderBase(TExtend parent) => OnAddingExtender(parent);
/// <summary>Initializes a new instance of the <see cref="ExtenderProviderBase{TExtend}"/> class.</summary>
/// <param name="container">The container.</param>
/// <exception cref="ArgumentNullException">container</exception>
protected ExtenderProviderBase(IContainer container) : this()
{
if (container is null)
throw new ArgumentNullException(nameof(container));
container.Add(this);
}
/// <summary>Occurs when a new extender is being added.</summary>
protected event EventHandler<AddExtenderEventArgs> AddingExtender;
/// <summary>Sets the site.</summary>
/// <value>The site.</value>
public override ISite Site
{
set
{
base.Site = value;
var parent = (value?.GetService(typeof(IDesignerHost)) as IDesignerHost)?.RootComponent as TExtend;
if (parent != null)
OnAddingExtender(parent);
}
}
/// <summary>Gets all extended components that have properties assigned.</summary>
/// <value>Returns a <see cref="IEnumerable{TExt}"/> value.</value>
protected IEnumerable<TExtend> ExtendedComponents => propHash.Keys;
/// <summary>Gets the known properties stored against all components.</summary>
/// <value>Returns a <see cref="IEnumerable{T}"/> value.</value>
protected IEnumerable<string> KnownProperties => propHash.Values.SelectMany(d => d.Keys).Distinct();
/// <summary>Signals the object that initialization is starting.</summary>
public virtual void BeginInit() { }
/// <summary>Determines whether this instance can extend the specified extendee.</summary>
/// <param name="extendee">The extendee.</param>
/// <returns><see langword="true"/> if this instance can extend the specified extendee; otherwise, <see langword="false"/>.</returns>
public virtual bool CanExtend(object extendee) => extendee is TExtend;
/// <summary>Signals the object that initialization is complete.</summary>
public virtual void EndInit() { }
/// <summary>Gets the property value.</summary>
/// <typeparam name="T">The type of the property to get.</typeparam>
/// <param name="form">The form.</param>
/// <param name="defaultValue">The default value.</param>
/// <param name="propName">Name of the field.</param>
/// <returns></returns>
protected virtual T GetPropertyValue<T>(TExtend form, T defaultValue = default, [CallerMemberName] string propName = "")
{
if (propName.StartsWith("Get"))
propName = propName.Remove(0, 3);
return propHash.TryGetValue(form, out var props) && props.TryGetValue(propName, out var prop) ? (T)prop : defaultValue;
}
/// <summary>Calls the <see cref="AddingExtender"/> event.</summary>
/// <param name="extender">The extender being added.</param>
protected virtual void OnAddingExtender(TExtend extender)
{
var args = new AddExtenderEventArgs(extender);
AddingExtender?.Invoke(this, args);
propHash[extender] = args.ExtenderProperties;
}
/// <summary>Sets the property value.</summary>
/// <typeparam name="T">The type of the property to set.</typeparam>
/// <param name="form">The form.</param>
/// <param name="value">The value.</param>
/// <param name="propName">Name of the field.</param>
protected virtual bool SetPropertyValue<T>(TExtend form, T value, [CallerMemberName] string propName = "")
{
if (!propHash.ContainsKey(form))
OnAddingExtender(form);
if (propName.StartsWith("Set"))
propName = propName.Remove(0, 3);
if (propHash[form].TryGetValue(propName, out var prop) && Equals(prop, value))
return false;
propHash[form][propName] = value;
return true;
}
/// <summary>Arguments for the <see cref="AddingExtender"/> event.</summary>
public class AddExtenderEventArgs : EventArgs
{
internal AddExtenderEventArgs(TExtend parent)
{
Extender = parent;
ExtenderProperties = new Dictionary<string, object>();
}
/// <summary>Gets the extender being added.</summary>
/// <value>The extender.</value>
public TExtend Extender { get; }
/// <summary>Gets or sets the property bag to be associated with this extender.</summary>
/// <value>The extender property bag.</value>
public Dictionary<string, object> ExtenderProperties { get; set; }
}
}
}