Built the Plugin-Info for Patchouli.

This commit is contained in:
feyris-tan 2026-01-21 21:38:48 +01:00
parent 82dabaabcb
commit 78bed400ee
15 changed files with 381 additions and 0 deletions

1
.gitignore vendored
View File

@ -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

View File

@ -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
{
}
}

View File

@ -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();
}
}

View File

@ -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
{
}
}

View File

@ -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);
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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<NeedsEntitlementAttribute>();
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<AutoconfigurableAttribute>();
_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<IncompleteAttribute>();
_incomplete = incompleteAttribute != null;
checkedIncomplete = true;
return _incomplete;
}
}
private string _displayName;
public string DisplayName
{
get
{
if (!string.IsNullOrEmpty(_displayName))
return _displayName;
DisplayNameAttribute displayNameAttribute = Type.GetCustomAttribute<DisplayNameAttribute>();
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<DescriptionAttribute>();
if (descriptionAttribute != null)
{
_description = descriptionAttribute.Desciption;
}
if (string.IsNullOrEmpty(_description))
{
_description = String.Format("TODO: Add {0} to {1}.", nameof(DescriptionAttribute), TypeName);
}
return Description;
}
}
}
}

View File

@ -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<Assembly> _loadedAssemblies;
private List<VoilePluginInfo> _knownDataStorages;
private List<VoilePluginInfo> _knownObjectStorages;
public bool ScanAssembly(Assembly assembly)
{
if (_loadedAssemblies == null)
_loadedAssemblies = new List<Assembly>();
if (_loadedAssemblies.Contains(assembly))
return false;
bool result = false;
Type[] types = assembly.GetTypes();
foreach (Type t in types)
{
VoilePluginAttribute? voilePluginAttribute = t.GetCustomAttribute<VoilePluginAttribute>();
if (voilePluginAttribute == null)
continue;
VoilePluginIdAttribute? voilePluginIdAttribute = t.GetCustomAttribute<VoilePluginIdAttribute>();
if (voilePluginIdAttribute == null)
continue;
VoilePluginInfo child = new VoilePluginInfo(t);
child.Id = voilePluginIdAttribute.Id;
if (t.IsAssignableTo(_dataStorageFactoryType))
{
if (_knownDataStorages == null)
_knownDataStorages = new List<VoilePluginInfo>();
child.Subsystem = VoileSubsystemType.DataStorage;
_knownDataStorages.Add(child);
result = true;
continue;
}
else if (t.IsAssignableTo(_objectStorageFactoryType))
{
if (_knownObjectStorages == null)
_knownObjectStorages = new List<VoilePluginInfo>();
child.Subsystem = VoileSubsystemType.ObjectStorage;
_knownObjectStorages.Add(child);
result = true;
continue;
}
else
{
}
}
return result;
}
}
}

View File

@ -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) { }
}
}

View File

@ -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
}
}

View File

@ -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) { }
}

View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Voile.Patchouli\Voile.Patchouli.csproj" />
</ItemGroup>
</Project>

View File

@ -7,6 +7,7 @@
<Project Path="Voile.Patchouli/Voile.Patchouli.csproj" Id="292d7909-c4ae-4345-b26e-34053d08ca96" />
<Project Path="Voile.Storage.Oracle/Voile.Storage.Oracle.csproj" />
<Project Path="Voile.Storage.Postgresql/Voile.Storage.Postgresql.csproj" />
<Project Path="Voile.Storage.Sqlite/Voile.Storage.Sqlite.csproj" Id="cea05f27-88bc-4598-b057-bc67fa6d7b55" />
<Project Path="Voile.Storage.SqlServer/Voile.Storage.SqlServer.csproj" />
<Project Path="Voile/Voile.csproj" />
</Solution>