mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-07 16:55:04 +00:00
fix: use correct line endings for verbatim strings
This commit is contained in:
@@ -1,47 +1,47 @@
|
||||
|
||||
|
||||
using Crestron.SimplSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Crestron.SimplSharp;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using Serilog.Events;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
|
||||
namespace PepperDash.Essentials.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a wrapper for a device factory, encapsulating the type of device, a description, and a factory method
|
||||
/// for creating device instances.
|
||||
/// <summary>
|
||||
/// Represents a wrapper for a device factory, encapsulating the type of device, a description, and a factory method
|
||||
/// for creating device instances.
|
||||
/// </summary>
|
||||
/// <remarks>This class is designed to provide a convenient way to store and manage metadata and factory methods
|
||||
/// for creating devices based on a given configuration.</remarks>
|
||||
public class DeviceFactoryWrapper
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the type associated with the current instance.
|
||||
/// <summary>
|
||||
/// Gets or sets the type associated with the current instance.
|
||||
/// </summary>
|
||||
public Type Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description associated with the object.
|
||||
/// <summary>
|
||||
/// Gets or sets the description associated with the object.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the factory method used to create an <see cref="IKeyed"/> instance based on the provided <see
|
||||
/// cref="DeviceConfig"/>.
|
||||
/// <summary>
|
||||
/// Gets or sets the factory method used to create an <see cref="IKeyed"/> instance based on the provided <see
|
||||
/// cref="DeviceConfig"/>.
|
||||
/// </summary>
|
||||
/// <remarks>The factory method allows customization of how <see cref="IKeyed"/> instances are created for
|
||||
/// specific <see cref="DeviceConfig"/> inputs. Ensure the delegate is not null before invoking it.</remarks>
|
||||
public Func<DeviceConfig, IKeyed> FactoryMethod { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DeviceFactoryWrapper"/> class with default values.
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DeviceFactoryWrapper"/> class with default values.
|
||||
/// </summary>
|
||||
/// <remarks>The <see cref="Type"/> property is initialized to <see langword="null"/>, and the <see
|
||||
/// cref="Description"/> property is set to "Not Available".</remarks>
|
||||
@@ -52,9 +52,9 @@ public class DeviceFactoryWrapper
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides functionality for managing and registering device factories, including loading plugin-based factories and
|
||||
/// retrieving devices based on their configuration.
|
||||
/// <summary>
|
||||
/// Provides functionality for managing and registering device factories, including loading plugin-based factories and
|
||||
/// retrieving devices based on their configuration.
|
||||
/// </summary>
|
||||
/// <remarks>The <see cref="DeviceFactory"/> class is responsible for discovering and registering device factories
|
||||
/// from plugins, as well as providing methods to retrieve devices based on their configuration. It maintains a
|
||||
@@ -62,9 +62,9 @@ public class DeviceFactoryWrapper
|
||||
/// class also handles metadata retrieval and secret management for device configurations.</remarks>
|
||||
public class DeviceFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DeviceFactory"/> class and loads all available device factories
|
||||
/// from the current assembly.
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DeviceFactory"/> class and loads all available device factories
|
||||
/// from the current assembly.
|
||||
/// </summary>
|
||||
/// <remarks>This constructor scans the executing assembly for types that implement the <see
|
||||
/// cref="IDeviceFactory"/> interface and are not abstract or interfaces. For each valid type, an instance is
|
||||
@@ -72,14 +72,14 @@ public class DeviceFactory
|
||||
/// instantiated, an informational log message is generated, and the process continues with the remaining
|
||||
/// types.</remarks>
|
||||
public DeviceFactory()
|
||||
{
|
||||
{
|
||||
var programAssemblies = Directory.GetFiles(InitialParametersClass.ProgramDirectory.ToString(), "*.dll");
|
||||
|
||||
foreach(var assembly in programAssemblies)
|
||||
foreach (var assembly in programAssemblies)
|
||||
{
|
||||
try
|
||||
{
|
||||
Assembly.LoadFrom(assembly);
|
||||
Assembly.LoadFrom(assembly);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -87,39 +87,39 @@ public class DeviceFactory
|
||||
}
|
||||
}
|
||||
|
||||
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
|
||||
// Loop through all loaded assemblies that contain at least 1 type that implements IDeviceFactory
|
||||
foreach (var assembly in loadedAssemblies)
|
||||
{
|
||||
Debug.LogDebug("loaded assembly: {assemblyName}", assembly.GetName().Name);
|
||||
|
||||
PluginLoader.AddLoadedAssembly(assembly.GetName().Name, assembly);
|
||||
|
||||
var types = assembly.GetTypes().Where(ct => typeof(IDeviceFactory).IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract);
|
||||
|
||||
if(types == null || !types.Any())
|
||||
{
|
||||
Debug.LogDebug("No DeviceFactory types found in assembly: {assemblyName}", assembly.GetName().Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
try
|
||||
{
|
||||
var factory = (IDeviceFactory)Activator.CreateInstance(type);
|
||||
LoadDeviceFactories(factory);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("Unable to load type: '{message}' DeviceFactory: {type}", e.Message, type.Name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var assembly in loadedAssemblies)
|
||||
{
|
||||
Debug.LogDebug("loaded assembly: {assemblyName}", assembly.GetName().Name);
|
||||
|
||||
PluginLoader.AddLoadedAssembly(assembly.GetName().Name, assembly);
|
||||
|
||||
var types = assembly.GetTypes().Where(ct => typeof(IDeviceFactory).IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract);
|
||||
|
||||
if (types == null || !types.Any())
|
||||
{
|
||||
Debug.LogDebug("No DeviceFactory types found in assembly: {assemblyName}", assembly.GetName().Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
try
|
||||
{
|
||||
var factory = (IDeviceFactory)Activator.CreateInstance(type);
|
||||
LoadDeviceFactories(factory);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("Unable to load type: '{message}' DeviceFactory: {type}", e.Message, type.Name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads device factories from the specified plugin device factory and registers them for use.
|
||||
/// </summary>
|
||||
@@ -137,8 +137,8 @@ public class DeviceFactory
|
||||
var snippetAttribute = deviceFactory.FactoryType.GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[];
|
||||
AddFactoryForType(typeName.ToLower(), description, deviceFactory.FactoryType, deviceFactory.BuildDevice);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A dictionary of factory methods, keyed by config types, added by plugins.
|
||||
/// These methods are looked up and called by GetDevice in this class.
|
||||
@@ -146,33 +146,33 @@ public class DeviceFactory
|
||||
private static readonly Dictionary<string, DeviceFactoryWrapper> FactoryMethods =
|
||||
new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a factory method for creating instances of a specific type.
|
||||
/// </summary>
|
||||
/// <remarks>This method associates a type name with a factory method, allowing instances of the type to
|
||||
/// be created dynamically. The factory method is stored internally and can be retrieved or invoked as
|
||||
/// needed.</remarks>
|
||||
/// <param name="typeName">The name of the type for which the factory method is being registered. This value cannot be null or empty.</param>
|
||||
/// <summary>
|
||||
/// Registers a factory method for creating instances of a specific type.
|
||||
/// </summary>
|
||||
/// <remarks>This method associates a type name with a factory method, allowing instances of the type to
|
||||
/// be created dynamically. The factory method is stored internally and can be retrieved or invoked as
|
||||
/// needed.</remarks>
|
||||
/// <param name="typeName">The name of the type for which the factory method is being registered. This value cannot be null or empty.</param>
|
||||
/// <param name="method">A delegate that defines the factory method. The delegate takes a <see cref="DeviceConfig"/> parameter and
|
||||
/// returns an instance of <see cref="IKeyed"/>.</param>
|
||||
public static void AddFactoryForType(string typeName, Func<DeviceConfig, IKeyed> method)
|
||||
{
|
||||
FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = method});
|
||||
}
|
||||
public static void AddFactoryForType(string typeName, Func<DeviceConfig, IKeyed> method)
|
||||
{
|
||||
FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = method });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a factory method for creating instances of a specific device type.
|
||||
/// </summary>
|
||||
/// <remarks>If a factory method for the specified <paramref name="typeName"/> already exists, the method
|
||||
/// will not overwrite it and will log an informational message instead.</remarks>
|
||||
/// <param name="typeName">The unique name of the device type. This serves as the key for identifying the factory method.</param>
|
||||
/// <param name="description">A brief description of the device type. This is used for informational purposes.</param>
|
||||
/// <param name="Type">The <see cref="Type"/> of the device being registered. This represents the runtime type of the device.</param>
|
||||
/// <summary>
|
||||
/// Registers a factory method for creating instances of a specific device type.
|
||||
/// </summary>
|
||||
/// <remarks>If a factory method for the specified <paramref name="typeName"/> already exists, the method
|
||||
/// will not overwrite it and will log an informational message instead.</remarks>
|
||||
/// <param name="typeName">The unique name of the device type. This serves as the key for identifying the factory method.</param>
|
||||
/// <param name="description">A brief description of the device type. This is used for informational purposes.</param>
|
||||
/// <param name="Type">The <see cref="Type"/> of the device being registered. This represents the runtime type of the device.</param>
|
||||
/// <param name="method">A factory method that takes a <see cref="DeviceConfig"/> as input and returns an instance of <see
|
||||
/// cref="IKeyed"/>.</param>
|
||||
public static void AddFactoryForType(string typeName, string description, Type Type, Func<DeviceConfig, IKeyed> method)
|
||||
{
|
||||
if(FactoryMethods.ContainsKey(typeName))
|
||||
if (FactoryMethods.ContainsKey(typeName))
|
||||
{
|
||||
Debug.LogInformation("Unable to add type: '{typeName}'. Already exists in DeviceFactory", typeName);
|
||||
return;
|
||||
@@ -190,7 +190,7 @@ public class DeviceFactory
|
||||
if (prop.Name.Equals("secret", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
var secret = GetSecret(prop.Children().First().ToObject<SecretsPropertiesConfig>());
|
||||
|
||||
|
||||
prop.Parent.Replace(secret);
|
||||
}
|
||||
if (prop.Value is not JObject recurseProp) return;
|
||||
@@ -203,7 +203,7 @@ public class DeviceFactory
|
||||
var secretProvider = SecretsManager.GetSecretProviderByKey(data.Provider);
|
||||
if (secretProvider == null) return null;
|
||||
var secret = secretProvider.GetSecret(data.Key);
|
||||
if (secret != null) return (string) secret.Value;
|
||||
if (secret != null) return (string)secret.Value;
|
||||
Debug.LogMessage(LogEventLevel.Debug,
|
||||
"Unable to retrieve secret {0}{1} - Make sure you've added it to the secrets provider",
|
||||
data.Provider, data.Key);
|
||||
@@ -211,20 +211,20 @@ public class DeviceFactory
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates and returns a device instance based on the provided <see cref="DeviceConfig"/>.
|
||||
/// </summary>
|
||||
/// <remarks>This method attempts to create a device using the type specified in the <paramref name="dc"/>
|
||||
/// parameter. If the type corresponds to a registered factory method, the device is created and returned. If the
|
||||
/// type is unrecognized or an exception occurs, the method logs the error and returns <see
|
||||
/// langword="null"/>.</remarks>
|
||||
/// <param name="dc">The configuration object containing the key, name, type, and properties required to create the device.</param>
|
||||
/// <summary>
|
||||
/// Creates and returns a device instance based on the provided <see cref="DeviceConfig"/>.
|
||||
/// </summary>
|
||||
/// <remarks>This method attempts to create a device using the type specified in the <paramref name="dc"/>
|
||||
/// parameter. If the type corresponds to a registered factory method, the device is created and returned. If the
|
||||
/// type is unrecognized or an exception occurs, the method logs the error and returns <see
|
||||
/// langword="null"/>.</remarks>
|
||||
/// <param name="dc">The configuration object containing the key, name, type, and properties required to create the device.</param>
|
||||
/// <returns>An instance of a device that implements <see cref="IKeyed"/>, or <see langword="null"/> if the device type is
|
||||
/// not recognized or an error occurs during creation.</returns>
|
||||
public static IKeyed GetDevice(DeviceConfig dc)
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
var localDc = new DeviceConfig(dc);
|
||||
|
||||
var key = localDc.Key;
|
||||
@@ -239,17 +239,17 @@ public class DeviceFactory
|
||||
var jProp = jObject.Properties();
|
||||
|
||||
CheckForSecrets(jProp);
|
||||
}
|
||||
|
||||
if (!FactoryMethods.TryGetValue(typeName, out var wrapper))
|
||||
{
|
||||
Debug.LogWarning("Device type '{typeName}' not found in DeviceFactory", typeName);
|
||||
return null;
|
||||
}
|
||||
|
||||
Debug.LogInformation("Loading '{type}' from {assemblyName}", typeName, wrapper.Type.Assembly.FullName);
|
||||
|
||||
// Check for types that have been added by plugin dlls.
|
||||
if (!FactoryMethods.TryGetValue(typeName, out var wrapper))
|
||||
{
|
||||
Debug.LogWarning("Device type '{typeName}' not found in DeviceFactory", typeName);
|
||||
return null;
|
||||
}
|
||||
|
||||
Debug.LogInformation("Loading '{type}' from {assemblyName}", typeName, wrapper.Type.Assembly.FullName);
|
||||
|
||||
// Check for types that have been added by plugin dlls.
|
||||
return wrapper.FactoryMethod(localDc);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -259,12 +259,12 @@ public class DeviceFactory
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays a list of device factory types that match the specified filter.
|
||||
/// </summary>
|
||||
/// <remarks>The method outputs the filtered list of device factory types to the console, including their
|
||||
/// key, type, and description. If a type is not specified by the plugin, it will be displayed as "Not Specified by
|
||||
/// Plugin."</remarks>
|
||||
/// <summary>
|
||||
/// Displays a list of device factory types that match the specified filter.
|
||||
/// </summary>
|
||||
/// <remarks>The method outputs the filtered list of device factory types to the console, including their
|
||||
/// key, type, and description. If a type is not specified by the plugin, it will be displayed as "Not Specified by
|
||||
/// Plugin."</remarks>
|
||||
/// <param name="filter">A string used to filter the device factory types by their keys. If the filter is null or empty, all device
|
||||
/// factory types are displayed.</param>
|
||||
public static void GetDeviceFactoryTypes(string filter)
|
||||
@@ -286,23 +286,23 @@ public class DeviceFactory
|
||||
}
|
||||
|
||||
CrestronConsole.ConsoleCommandResponse(
|
||||
@"Type: '{0}'
|
||||
Type: '{1}'
|
||||
Description: {2}{3}", type.Key, Type, description, CrestronEnvironment.NewLine);
|
||||
"Type: '{0}'\r\n" +
|
||||
" Type: '{1}'\r\n" +
|
||||
" Description: {2}{3}", type.Key, Type, description, CrestronEnvironment.NewLine);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a dictionary of device factory wrappers, optionally filtered by a specified string.
|
||||
/// </summary>
|
||||
/// <param name="filter">A string used to filter the dictionary keys. Only entries with keys containing the specified filter will be
|
||||
/// included. If <see langword="null"/> or empty, all entries are returned.</param>
|
||||
/// <summary>
|
||||
/// Retrieves a dictionary of device factory wrappers, optionally filtered by a specified string.
|
||||
/// </summary>
|
||||
/// <param name="filter">A string used to filter the dictionary keys. Only entries with keys containing the specified filter will be
|
||||
/// included. If <see langword="null"/> or empty, all entries are returned.</param>
|
||||
/// <returns>A dictionary where the keys are strings representing device identifiers and the values are <see
|
||||
/// cref="DeviceFactoryWrapper"/> instances. The dictionary may be empty if no entries match the filter.</returns>
|
||||
public static Dictionary<string, DeviceFactoryWrapper> GetDeviceFactoryDictionary(string filter)
|
||||
{
|
||||
return string.IsNullOrEmpty(filter)
|
||||
? FactoryMethods
|
||||
: FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value);
|
||||
}
|
||||
public static Dictionary<string, DeviceFactoryWrapper> GetDeviceFactoryDictionary(string filter)
|
||||
{
|
||||
return string.IsNullOrEmpty(filter)
|
||||
? FactoryMethods
|
||||
: FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user