From 78bed400eecf16e6acb021983a108af4d6bfc5e6 Mon Sep 17 00:00:00 2001 From: feyris-tan <4116042+feyris-tan@users.noreply.github.com> Date: Wed, 21 Jan 2026 21:38:48 +0100 Subject: [PATCH] Built the Plugin-Info for Patchouli. --- .gitignore | 1 + Voile.Patchouli/Data/IVoileDataStorage.cs | 12 ++ .../Data/IVoileDataStorageFactory.cs | 13 ++ Voile.Patchouli/Data/IVoileObjectStorage.cs | 12 ++ .../Data/IVoileObjectStorageFactory.cs | 15 ++ .../Reflection/DescriptionAttribute.cs | 20 +++ .../Reflection/DisplayNameAttribute.cs | 19 +++ .../Reflection/VoilePluginIdAttribute.cs | 19 +++ Voile.Patchouli/Reflection/VoilePluginInfo.cs | 135 ++++++++++++++++++ .../Reflection/VoilePluginManager.cs | 82 +++++++++++ .../Reflection/VoileReflectionException.cs | 21 +++ .../Reflection/VoileSubsystemType.cs | 14 ++ Voile.Patchouli/VoileException.cs | 4 + .../Voile.Storage.Sqlite.csproj | 13 ++ Voile.slnx | 1 + 15 files changed, 381 insertions(+) create mode 100644 Voile.Patchouli/Data/IVoileDataStorage.cs create mode 100644 Voile.Patchouli/Data/IVoileDataStorageFactory.cs create mode 100644 Voile.Patchouli/Data/IVoileObjectStorage.cs create mode 100644 Voile.Patchouli/Data/IVoileObjectStorageFactory.cs create mode 100644 Voile.Patchouli/Reflection/DescriptionAttribute.cs create mode 100644 Voile.Patchouli/Reflection/DisplayNameAttribute.cs create mode 100644 Voile.Patchouli/Reflection/VoilePluginIdAttribute.cs create mode 100644 Voile.Patchouli/Reflection/VoilePluginInfo.cs create mode 100644 Voile.Patchouli/Reflection/VoilePluginManager.cs create mode 100644 Voile.Patchouli/Reflection/VoileReflectionException.cs create mode 100644 Voile.Patchouli/Reflection/VoileSubsystemType.cs create mode 100644 Voile.Storage.Sqlite/Voile.Storage.Sqlite.csproj diff --git a/.gitignore b/.gitignore index db09243..a7e79f2 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ /Voile.Storage.Oracle/bin/Debug/net8.0 /Voile.Storage.Postgresql/bin/Debug/net8.0 /Voile.Storage.SqlServer/bin/Debug/net8.0 +/Voile.Storage.Sqlite/obj diff --git a/Voile.Patchouli/Data/IVoileDataStorage.cs b/Voile.Patchouli/Data/IVoileDataStorage.cs new file mode 100644 index 0000000..b79e19b --- /dev/null +++ b/Voile.Patchouli/Data/IVoileDataStorage.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Voile.Patchouli.Data +{ + public interface IVoileDataStorage + { + } +} diff --git a/Voile.Patchouli/Data/IVoileDataStorageFactory.cs b/Voile.Patchouli/Data/IVoileDataStorageFactory.cs new file mode 100644 index 0000000..96d8b7a --- /dev/null +++ b/Voile.Patchouli/Data/IVoileDataStorageFactory.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Voile.Patchouli.Data +{ + public interface IVoileDataStorageFactory + { + IVoileDataStorage CreateDataStorage(); + } +} diff --git a/Voile.Patchouli/Data/IVoileObjectStorage.cs b/Voile.Patchouli/Data/IVoileObjectStorage.cs new file mode 100644 index 0000000..0cdd5a6 --- /dev/null +++ b/Voile.Patchouli/Data/IVoileObjectStorage.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Voile.Patchouli.Data +{ + public interface IVoileObjectStorage + { + } +} diff --git a/Voile.Patchouli/Data/IVoileObjectStorageFactory.cs b/Voile.Patchouli/Data/IVoileObjectStorageFactory.cs new file mode 100644 index 0000000..58b6390 --- /dev/null +++ b/Voile.Patchouli/Data/IVoileObjectStorageFactory.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Voile.Patchouli.Data +{ + public interface IVoileObjectStorageFactory + { + IVoileObjectStorage CreateObjectStorage(); + + bool IsEquipvalentDataStorageFactory(IVoileDataStorageFactory dataStorageFactory); + } +} diff --git a/Voile.Patchouli/Reflection/DescriptionAttribute.cs b/Voile.Patchouli/Reflection/DescriptionAttribute.cs new file mode 100644 index 0000000..41edf9d --- /dev/null +++ b/Voile.Patchouli/Reflection/DescriptionAttribute.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Voile.Patchouli.Reflection +{ + [System.AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] + sealed class DescriptionAttribute : Attribute + { + // This is a positional argument + public DescriptionAttribute(string positionalString) + { + Desciption = positionalString; + } + + public string Desciption { get; } + } +} diff --git a/Voile.Patchouli/Reflection/DisplayNameAttribute.cs b/Voile.Patchouli/Reflection/DisplayNameAttribute.cs new file mode 100644 index 0000000..46b7f7b --- /dev/null +++ b/Voile.Patchouli/Reflection/DisplayNameAttribute.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Voile.Patchouli.Reflection +{ + [System.AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] + public class DisplayNameAttribute : Attribute + { + public DisplayNameAttribute(string displayName) + { + DisplayName = displayName; + } + + public string DisplayName { get; } + } +} diff --git a/Voile.Patchouli/Reflection/VoilePluginIdAttribute.cs b/Voile.Patchouli/Reflection/VoilePluginIdAttribute.cs new file mode 100644 index 0000000..2dfca03 --- /dev/null +++ b/Voile.Patchouli/Reflection/VoilePluginIdAttribute.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Voile.Patchouli.Reflection +{ + [System.AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] + public sealed class VoilePluginIdAttribute : Attribute + { + public VoilePluginIdAttribute(int id) + { + Id = id; + } + + public int Id { get; } + } +} diff --git a/Voile.Patchouli/Reflection/VoilePluginInfo.cs b/Voile.Patchouli/Reflection/VoilePluginInfo.cs new file mode 100644 index 0000000..2af0457 --- /dev/null +++ b/Voile.Patchouli/Reflection/VoilePluginInfo.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Voile.Common.DRM; +using Voile.Common.Reflection; + +namespace Voile.Patchouli.Reflection +{ + public class VoilePluginInfo + { + internal VoilePluginInfo(Type t) + { + Type = t; + } + + private Type Type { get; } + + public string TypeName { get => Type.Name; } + public int Id { get; internal set; } + public VoileSubsystemType Subsystem { get; internal set; } + + private object _instance; + public object GetPluginInstance() + { + if (_instance != null) + return _instance; + + ConstructorInfo? constructorInfo = Type.GetConstructor(new Type[0] { }); + if (constructorInfo == null) + { + throw new VoileReflectionException(String.Format("{0} does not provide a parameterless constructor.", TypeName)); + } + + object result = constructorInfo.Invoke(new object[0] { }); + _instance = result; + return result; + } + + private bool checkedNeededEntitlement; + private Guid? _neededEntitlement; + public Guid? NeededEntitlement + { + get + { + if (checkedNeededEntitlement) + return _neededEntitlement; + + NeedsEntitlementAttribute? needsEntitlementAttribute = Type.GetCustomAttribute(); + if (needsEntitlementAttribute != null) + { + _neededEntitlement = needsEntitlementAttribute.Guid; + } + checkedNeededEntitlement = true; + return _neededEntitlement; + } + } + + private bool checkedAutoconfigurable; + public bool _autoconfigurable; + public bool Autoconfigurable + { + get + { + if (checkedAutoconfigurable) + return _autoconfigurable; + + AutoconfigurableAttribute autoconfigurableAttribute = Type.GetCustomAttribute(); + _autoconfigurable = autoconfigurableAttribute != null; + checkedAutoconfigurable = true; + return _autoconfigurable; + } + } + + private bool checkedIncomplete; + private bool _incomplete; + public bool Incomplete + { + get + { + if (checkedIncomplete) + return _incomplete; + + IncompleteAttribute incompleteAttribute = Type.GetCustomAttribute(); + _incomplete = incompleteAttribute != null; + checkedIncomplete = true; + return _incomplete; + } + } + + private string _displayName; + public string DisplayName + { + get + { + if (!string.IsNullOrEmpty(_displayName)) + return _displayName; + + DisplayNameAttribute displayNameAttribute = Type.GetCustomAttribute(); + if (displayNameAttribute != null) + { + _displayName = displayNameAttribute.DisplayName; + } + if (string.IsNullOrEmpty(_displayName)) + { + _displayName = TypeName; + } + return _displayName; + } + } + + private string _description; + public string Description + { + get + { + if (!string.IsNullOrEmpty(_description)) + return _description; + + DescriptionAttribute descriptionAttribute = Type.GetCustomAttribute(); + if (descriptionAttribute != null) + { + _description = descriptionAttribute.Desciption; + } + if (string.IsNullOrEmpty(_description)) + { + _description = String.Format("TODO: Add {0} to {1}.", nameof(DescriptionAttribute), TypeName); + } + return Description; + } + } + } +} diff --git a/Voile.Patchouli/Reflection/VoilePluginManager.cs b/Voile.Patchouli/Reflection/VoilePluginManager.cs new file mode 100644 index 0000000..7fcc913 --- /dev/null +++ b/Voile.Patchouli/Reflection/VoilePluginManager.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Voile.Common.Reflection; +using Voile.Patchouli.Data; + +namespace Voile.Patchouli.Reflection +{ + public class VoilePluginManager + { + private VoilePluginManager() { } + + public static VoilePluginManager _instance; + private static Type _dataStorageFactoryType = typeof(IVoileDataStorageFactory); + private static Type _objectStorageFactoryType = typeof(IVoileObjectStorageFactory); + + public static VoilePluginManager GetInstance() + { + if (_instance == null) + { + _instance = new VoilePluginManager(); + } + return _instance; + } + + private List _loadedAssemblies; + private List _knownDataStorages; + private List _knownObjectStorages; + + public bool ScanAssembly(Assembly assembly) + { + if (_loadedAssemblies == null) + _loadedAssemblies = new List(); + if (_loadedAssemblies.Contains(assembly)) + return false; + + bool result = false; + + Type[] types = assembly.GetTypes(); + foreach (Type t in types) + { + VoilePluginAttribute? voilePluginAttribute = t.GetCustomAttribute(); + if (voilePluginAttribute == null) + continue; + + VoilePluginIdAttribute? voilePluginIdAttribute = t.GetCustomAttribute(); + if (voilePluginIdAttribute == null) + continue; + + VoilePluginInfo child = new VoilePluginInfo(t); + child.Id = voilePluginIdAttribute.Id; + + if (t.IsAssignableTo(_dataStorageFactoryType)) + { + if (_knownDataStorages == null) + _knownDataStorages = new List(); + child.Subsystem = VoileSubsystemType.DataStorage; + _knownDataStorages.Add(child); + result = true; + continue; + } + else if (t.IsAssignableTo(_objectStorageFactoryType)) + { + if (_knownObjectStorages == null) + _knownObjectStorages = new List(); + child.Subsystem = VoileSubsystemType.ObjectStorage; + _knownObjectStorages.Add(child); + result = true; + continue; + } + else + { + + } + } + return result; + } + } +} diff --git a/Voile.Patchouli/Reflection/VoileReflectionException.cs b/Voile.Patchouli/Reflection/VoileReflectionException.cs new file mode 100644 index 0000000..14d04a3 --- /dev/null +++ b/Voile.Patchouli/Reflection/VoileReflectionException.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Voile.Common; + +namespace Voile.Patchouli.Reflection +{ + + [Serializable] + public class VoileReflectionException : VoileException + { + public VoileReflectionException() { } + public VoileReflectionException(string message) : base(message) { } + public VoileReflectionException(string message, Exception inner) : base(message, inner) { } + protected VoileReflectionException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base(info, context) { } + } +} diff --git a/Voile.Patchouli/Reflection/VoileSubsystemType.cs b/Voile.Patchouli/Reflection/VoileSubsystemType.cs new file mode 100644 index 0000000..249db04 --- /dev/null +++ b/Voile.Patchouli/Reflection/VoileSubsystemType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Voile.Patchouli.Reflection +{ + public enum VoileSubsystemType + { + DataStorage, + ObjectStorage + } +} diff --git a/Voile.Patchouli/VoileException.cs b/Voile.Patchouli/VoileException.cs index a721f17..847ce01 100644 --- a/Voile.Patchouli/VoileException.cs +++ b/Voile.Patchouli/VoileException.cs @@ -13,4 +13,8 @@ public class VoileException : Exception public VoileException(string message, Exception inner) : base(message, inner) { } + + protected VoileException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base(info, context) { } } diff --git a/Voile.Storage.Sqlite/Voile.Storage.Sqlite.csproj b/Voile.Storage.Sqlite/Voile.Storage.Sqlite.csproj new file mode 100644 index 0000000..e6acd33 --- /dev/null +++ b/Voile.Storage.Sqlite/Voile.Storage.Sqlite.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/Voile.slnx b/Voile.slnx index bb320f1..0c07176 100644 --- a/Voile.slnx +++ b/Voile.slnx @@ -7,6 +7,7 @@ +