From 29debac9e1da99e8559c057b858c65186fe69d60 Mon Sep 17 00:00:00 2001
From: MidoriKami <9083275+MidoriKami@users.noreply.github.com>
Date: Sun, 30 Jul 2023 18:26:50 -0700
Subject: [PATCH 1/5] Character.cs Obsoletes
---
.../ClientState/Objects/Types/Character.cs | 22 +++++++++----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/Dalamud/Game/ClientState/Objects/Types/Character.cs b/Dalamud/Game/ClientState/Objects/Types/Character.cs
index cdd1515b0..ee8418362 100644
--- a/Dalamud/Game/ClientState/Objects/Types/Character.cs
+++ b/Dalamud/Game/ClientState/Objects/Types/Character.cs
@@ -26,52 +26,52 @@ public unsafe class Character : GameObject
///
/// Gets the current HP of this Chara.
///
- public uint CurrentHp => this.Struct->Health;
+ public uint CurrentHp => this.Struct->CharacterData.Health;
///
/// Gets the maximum HP of this Chara.
///
- public uint MaxHp => this.Struct->MaxHealth;
+ public uint MaxHp => this.Struct->CharacterData.MaxHealth;
///
/// Gets the current MP of this Chara.
///
- public uint CurrentMp => this.Struct->Mana;
+ public uint CurrentMp => this.Struct->CharacterData.Mana;
///
/// Gets the maximum MP of this Chara.
///
- public uint MaxMp => this.Struct->MaxMana;
+ public uint MaxMp => this.Struct->CharacterData.MaxMana;
///
/// Gets the current GP of this Chara.
///
- public uint CurrentGp => this.Struct->GatheringPoints;
+ public uint CurrentGp => this.Struct->CharacterData.GatheringPoints;
///
/// Gets the maximum GP of this Chara.
///
- public uint MaxGp => this.Struct->MaxGatheringPoints;
+ public uint MaxGp => this.Struct->CharacterData.MaxGatheringPoints;
///
/// Gets the current CP of this Chara.
///
- public uint CurrentCp => this.Struct->CraftingPoints;
+ public uint CurrentCp => this.Struct->CharacterData.CraftingPoints;
///
/// Gets the maximum CP of this Chara.
///
- public uint MaxCp => this.Struct->MaxCraftingPoints;
+ public uint MaxCp => this.Struct->CharacterData.MaxCraftingPoints;
///
/// Gets the ClassJob of this Chara.
///
- public ExcelResolver ClassJob => new(this.Struct->ClassJob);
+ public ExcelResolver ClassJob => new(this.Struct->CharacterData.ClassJob);
///
/// Gets the level of this Chara.
///
- public byte Level => this.Struct->Level;
+ public byte Level => this.Struct->CharacterData.Level;
///
/// Gets a byte array describing the visual appearance of this Chara.
@@ -97,7 +97,7 @@ public unsafe class Character : GameObject
///
/// Gets the current online status of the character.
///
- public ExcelResolver OnlineStatus => new(this.Struct->OnlineStatus);
+ public ExcelResolver OnlineStatus => new(this.Struct->CharacterData.OnlineStatus);
///
/// Gets the status flags.
From ee181c9a896fcc7bc32e063145030fdb4ced00a4 Mon Sep 17 00:00:00 2001
From: goat
Date: Wed, 2 Aug 2023 23:03:58 +0200
Subject: [PATCH 2/5] feat(DI): support scoped services with interfaces
---
Dalamud/IoC/Internal/ServiceContainer.cs | 98 +++++++++++++-----------
Dalamud/ServiceManager.cs | 11 ++-
2 files changed, 64 insertions(+), 45 deletions(-)
diff --git a/Dalamud/IoC/Internal/ServiceContainer.cs b/Dalamud/IoC/Internal/ServiceContainer.cs
index feac634f3..db748303e 100644
--- a/Dalamud/IoC/Internal/ServiceContainer.cs
+++ b/Dalamud/IoC/Internal/ServiceContainer.cs
@@ -12,6 +12,9 @@ namespace Dalamud.IoC.Internal;
///
/// A simple singleton-only IOC container that provides (optional) version-based dependency resolution.
+///
+/// This is only used to resolve dependencies for plugins.
+/// Dalamud services are constructed via Service{T}.ConstructObject at the moment.
///
internal class ServiceContainer : IServiceProvider, IServiceType
{
@@ -31,7 +34,7 @@ internal class ServiceContainer : IServiceProvider, IServiceType
/// Register a singleton object of any type into the current IOC container.
///
/// The existing instance to register in the container.
- /// The interface to register.
+ /// The type to register.
public void RegisterSingleton(Task instance)
{
if (instance == null)
@@ -40,19 +43,27 @@ internal class ServiceContainer : IServiceProvider, IServiceType
}
this.instances[typeof(T)] = new(instance.ContinueWith(x => new WeakReference(x.Result)), typeof(T));
+ this.RegisterInterfaces(typeof(T));
+ }
- var resolveViaTypes = typeof(T)
- .GetCustomAttributes()
- .OfType()
- .Select(x => x.GetType().GetGenericArguments().First());
+ ///
+ /// Register the interfaces that can resolve this type.
+ ///
+ /// The type to register.
+ public void RegisterInterfaces(Type type)
+ {
+ var resolveViaTypes = type
+ .GetCustomAttributes()
+ .OfType()
+ .Select(x => x.GetType().GetGenericArguments().First());
foreach (var resolvableType in resolveViaTypes)
{
- Log.Verbose("=> {InterfaceName} provides for {TName}", resolvableType.FullName ?? "???", typeof(T).FullName ?? "???");
+ Log.Verbose("=> {InterfaceName} provides for {TName}", resolvableType.FullName ?? "???", type.FullName ?? "???");
Debug.Assert(!this.interfaceToTypeMap.ContainsKey(resolvableType), "A service already implements this interface, this is not allowed");
- Debug.Assert(typeof(T).IsAssignableTo(resolvableType), "Service does not inherit from indicated ResolveVia type");
+ Debug.Assert(type.IsAssignableTo(resolvableType), "Service does not inherit from indicated ResolveVia type");
- this.interfaceToTypeMap[resolvableType] = typeof(T);
+ this.interfaceToTypeMap[resolvableType] = type;
}
}
@@ -95,18 +106,7 @@ internal class ServiceContainer : IServiceProvider, IServiceType
parameters
.Select(async p =>
{
- if (p.parameterType.GetCustomAttribute() != null)
- {
- if (scopeImpl == null)
- {
- Log.Error("Failed to create {TypeName}, depends on scoped service but no scope", objectType.FullName!);
- return null;
- }
-
- return await scopeImpl.CreatePrivateScopedObject(p.parameterType, scopedObjects);
- }
-
- var service = await this.GetService(p.parameterType, scopedObjects);
+ var service = await this.GetService(p.parameterType, scopeImpl, scopedObjects);
if (service == null)
{
@@ -168,22 +168,7 @@ internal class ServiceContainer : IServiceProvider, IServiceType
foreach (var prop in props)
{
- object service = null;
-
- if (prop.propertyInfo.PropertyType.GetCustomAttribute() != null)
- {
- if (scopeImpl == null)
- {
- Log.Error("Failed to create {TypeName}, depends on scoped service but no scope", objectType.FullName!);
- }
- else
- {
- service = await scopeImpl.CreatePrivateScopedObject(prop.propertyInfo.PropertyType, publicScopes);
- }
- }
-
- service ??= await this.GetService(prop.propertyInfo.PropertyType, publicScopes);
-
+ var service = await this.GetService(prop.propertyInfo.PropertyType, scopeImpl, publicScopes);
if (service == null)
{
Log.Error("Requested service type {TypeName} was not available (null)", prop.propertyInfo.PropertyType.FullName!);
@@ -203,7 +188,7 @@ internal class ServiceContainer : IServiceProvider, IServiceType
public IServiceScope GetScope() => new ServiceScopeImpl(this);
///
- object? IServiceProvider.GetService(Type serviceType) => this.GetService(serviceType);
+ object? IServiceProvider.GetService(Type serviceType) => this.GetSingletonService(serviceType);
private static bool CheckInterfaceVersion(RequiredVersionAttribute? requiredVersion, Type parameterType)
{
@@ -228,9 +213,23 @@ internal class ServiceContainer : IServiceProvider, IServiceType
return false;
}
- private async Task