From 4e20ef1552a1d258ed6eea9b812dc6c3478ad42b Mon Sep 17 00:00:00 2001 From: bonbon Date: Sun, 11 Aug 2024 14:50:43 +0900 Subject: [PATCH 1/4] ??? MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Microsoft.MinIocが参照できなくなったのでContainer.csをプロジェクトに埋め込んだ --- source/ACT.Hojoring.sln | 2 +- .../FFXIV.Framework/Common/Container.cs | 274 ++++++++++++++++++ .../FFXIV.Framework/FFXIV.Framework.csproj | 1 + 3 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 source/FFXIV.Framework/FFXIV.Framework/Common/Container.cs diff --git a/source/ACT.Hojoring.sln b/source/ACT.Hojoring.sln index 8c8ed8c6..47b03c6b 100644 --- a/source/ACT.Hojoring.sln +++ b/source/ACT.Hojoring.sln @@ -200,8 +200,8 @@ Global {C1BC2D6E-E10D-4A7F-900B-5FD84F39BF0A} = {EC98C548-6268-4B67-BC45-88DCD9B63960} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {2A11DDD1-7A46-4236-969A-3942CBE6A01A} SolutionGuid = {91001FDF-B748-4513-A399-35F7E9BD37F8} + SolutionGuid = {2A11DDD1-7A46-4236-969A-3942CBE6A01A} EndGlobalSection GlobalSection(SharedMSBuildProjectFiles) = preSolution ACT.Hojoring.Shared\ACT.Hojoring.Shared.projitems*{450f38fa-7f7d-41b9-9bbb-503efc6c0a72}*SharedItemsImports = 4 diff --git a/source/FFXIV.Framework/FFXIV.Framework/Common/Container.cs b/source/FFXIV.Framework/FFXIV.Framework/Common/Container.cs new file mode 100644 index 00000000..9ed96961 --- /dev/null +++ b/source/FFXIV.Framework/FFXIV.Framework/Common/Container.cs @@ -0,0 +1,274 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace Microsoft.MinIoC +{ + /// + /// Inversion of control container handles dependency injection for registered types + /// + class Container : Container.IScope + { + #region Public interfaces + /// + /// Represents a scope in which per-scope objects are instantiated a single time + /// + public interface IScope : IDisposable, IServiceProvider + { + } + + /// + /// IRegisteredType is return by Container.Register and allows further configuration for the registration + /// + public interface IRegisteredType + { + /// + /// Make registered type a singleton + /// + void AsSingleton(); + + /// + /// Make registered type a per-scope type (single instance within a Scope) + /// + void PerScope(); + } + #endregion + + // Map of registered types + private readonly Dictionary> _registeredTypes = new Dictionary>(); + + // Lifetime management + private readonly ContainerLifetime _lifetime; + + /// + /// Creates a new instance of IoC Container + /// + public Container() => _lifetime = new ContainerLifetime(t => _registeredTypes[t]); + + /// + /// Registers a factory function which will be called to resolve the specified interface + /// + /// Interface to register + /// Factory function + /// + public IRegisteredType Register(Type @interface, Func factory) + => RegisterType(@interface, _ => factory()); + + /// + /// Registers an implementation type for the specified interface + /// + /// Interface to register + /// Implementing type + /// + public IRegisteredType Register(Type @interface, Type implementation) + => RegisterType(@interface, FactoryFromType(implementation)); + + private IRegisteredType RegisterType(Type itemType, Func factory) + => new RegisteredType(itemType, f => _registeredTypes[itemType] = f, factory); + + /// + /// Returns the object registered for the given type, if registered + /// + /// Type as registered with the container + /// Instance of the registered type, if registered; otherwise + public object GetService(Type type) + { + Func registeredType; + + if (!_registeredTypes.TryGetValue(type, out registeredType)) + { + return null; + } + + return registeredType(_lifetime); + } + + /// + /// Creates a new scope + /// + /// Scope object + public IScope CreateScope() => new ScopeLifetime(_lifetime); + + /// + /// Disposes any objects owned by this container. + /// + public void Dispose() => _lifetime.Dispose(); + + #region Lifetime management + // ILifetime management adds resolution strategies to an IScope + interface ILifetime : IScope + { + object GetServiceAsSingleton(Type type, Func factory); + + object GetServicePerScope(Type type, Func factory); + } + + // ObjectCache provides common caching logic for lifetimes + abstract class ObjectCache + { + // Instance cache + private readonly ConcurrentDictionary _instanceCache = new ConcurrentDictionary(); + + // Get from cache or create and cache object + protected object GetCached(Type type, Func factory, ILifetime lifetime) + => _instanceCache.GetOrAdd(type, _ => factory(lifetime)); + + public void Dispose() + { + foreach (var obj in _instanceCache.Values) + (obj as IDisposable)?.Dispose(); + } + } + + // Container lifetime management + class ContainerLifetime : ObjectCache, ILifetime + { + // Retrieves the factory functino from the given type, provided by owning container + public Func> GetFactory { get; private set; } + + public ContainerLifetime(Func> getFactory) => GetFactory = getFactory; + + public object GetService(Type type) => GetFactory(type)(this); + + // Singletons get cached per container + public object GetServiceAsSingleton(Type type, Func factory) + => GetCached(type, factory, this); + + // At container level, per-scope items are equivalent to singletons + public object GetServicePerScope(Type type, Func factory) + => GetServiceAsSingleton(type, factory); + } + + // Per-scope lifetime management + class ScopeLifetime : ObjectCache, ILifetime + { + // Singletons come from parent container's lifetime + private readonly ContainerLifetime _parentLifetime; + + public ScopeLifetime(ContainerLifetime parentContainer) => _parentLifetime = parentContainer; + + public object GetService(Type type) => _parentLifetime.GetFactory(type)(this); + + // Singleton resolution is delegated to parent lifetime + public object GetServiceAsSingleton(Type type, Func factory) + => _parentLifetime.GetServiceAsSingleton(type, factory); + + // Per-scope objects get cached + public object GetServicePerScope(Type type, Func factory) + => GetCached(type, factory, this); + } + #endregion + + #region Container items + // Compiles a lambda that calls the given type's first constructor resolving arguments + private static Func FactoryFromType(Type itemType) + { + // Get first constructor for the type + var constructors = itemType.GetConstructors(); + if (constructors.Length == 0) + { + // If no public constructor found, search for an internal constructor + constructors = itemType.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic); + } + var constructor = constructors.First(); + + // Compile constructor call as a lambda expression + var arg = Expression.Parameter(typeof(ILifetime)); + return (Func)Expression.Lambda( + Expression.New(constructor, constructor.GetParameters().Select( + param => + { + var resolve = new Func( + lifetime => lifetime.GetService(param.ParameterType)); + return Expression.Convert( + Expression.Call(Expression.Constant(resolve.Target), resolve.Method, arg), + param.ParameterType); + })), + arg).Compile(); + } + + // RegisteredType is supposed to be a short lived object tying an item to its container + // and allowing users to mark it as a singleton or per-scope item + class RegisteredType : IRegisteredType + { + private readonly Type _itemType; + private readonly Action> _registerFactory; + private readonly Func _factory; + + public RegisteredType(Type itemType, Action> registerFactory, Func factory) + { + _itemType = itemType; + _registerFactory = registerFactory; + _factory = factory; + + registerFactory(_factory); + } + + public void AsSingleton() + => _registerFactory(lifetime => lifetime.GetServiceAsSingleton(_itemType, _factory)); + + public void PerScope() + => _registerFactory(lifetime => lifetime.GetServicePerScope(_itemType, _factory)); + } + #endregion + } + + /// + /// Extension methods for Container + /// + static class ContainerExtensions + { + /// + /// Registers an implementation type for the specified interface + /// + /// Interface to register + /// This container instance + /// Implementing type + /// IRegisteredType object + public static Container.IRegisteredType Register(this Container container, Type type) + => container.Register(typeof(T), type); + + /// + /// Registers an implementation type for the specified interface + /// + /// Interface to register + /// Implementing type + /// This container instance + /// IRegisteredType object + public static Container.IRegisteredType Register(this Container container) + where TImplementation : TInterface + => container.Register(typeof(TInterface), typeof(TImplementation)); + + /// + /// Registers a factory function which will be called to resolve the specified interface + /// + /// Interface to register + /// This container instance + /// Factory method + /// IRegisteredType object + public static Container.IRegisteredType Register(this Container container, Func factory) + => container.Register(typeof(T), () => factory()); + + /// + /// Registers a type + /// + /// This container instance + /// Type to register + /// IRegisteredType object + public static Container.IRegisteredType Register(this Container container) + => container.Register(typeof(T), typeof(T)); + + /// + /// Returns an implementation of the specified interface + /// + /// Interface type + /// This scope instance + /// Object implementing the interface + public static T Resolve(this Container.IScope scope) => (T)scope.GetService(typeof(T)); + } +} \ No newline at end of file diff --git a/source/FFXIV.Framework/FFXIV.Framework/FFXIV.Framework.csproj b/source/FFXIV.Framework/FFXIV.Framework/FFXIV.Framework.csproj index f1e78147..6a00578d 100644 --- a/source/FFXIV.Framework/FFXIV.Framework/FFXIV.Framework.csproj +++ b/source/FFXIV.Framework/FFXIV.Framework/FFXIV.Framework.csproj @@ -99,6 +99,7 @@ + From 85674fc1198d11e6ac4115732d2ca6e92d243bcd Mon Sep 17 00:00:00 2001 From: bonbon Date: Sun, 11 Aug 2024 15:08:11 +0900 Subject: [PATCH 2/4] Revert "???" This reverts commit 4e20ef1552a1d258ed6eea9b812dc6c3478ad42b. --- source/ACT.Hojoring.sln | 2 +- .../FFXIV.Framework/Common/Container.cs | 274 ------------------ .../FFXIV.Framework/FFXIV.Framework.csproj | 1 - 3 files changed, 1 insertion(+), 276 deletions(-) delete mode 100644 source/FFXIV.Framework/FFXIV.Framework/Common/Container.cs diff --git a/source/ACT.Hojoring.sln b/source/ACT.Hojoring.sln index 47b03c6b..8c8ed8c6 100644 --- a/source/ACT.Hojoring.sln +++ b/source/ACT.Hojoring.sln @@ -200,8 +200,8 @@ Global {C1BC2D6E-E10D-4A7F-900B-5FD84F39BF0A} = {EC98C548-6268-4B67-BC45-88DCD9B63960} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {91001FDF-B748-4513-A399-35F7E9BD37F8} SolutionGuid = {2A11DDD1-7A46-4236-969A-3942CBE6A01A} + SolutionGuid = {91001FDF-B748-4513-A399-35F7E9BD37F8} EndGlobalSection GlobalSection(SharedMSBuildProjectFiles) = preSolution ACT.Hojoring.Shared\ACT.Hojoring.Shared.projitems*{450f38fa-7f7d-41b9-9bbb-503efc6c0a72}*SharedItemsImports = 4 diff --git a/source/FFXIV.Framework/FFXIV.Framework/Common/Container.cs b/source/FFXIV.Framework/FFXIV.Framework/Common/Container.cs deleted file mode 100644 index 9ed96961..00000000 --- a/source/FFXIV.Framework/FFXIV.Framework/Common/Container.cs +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; - -namespace Microsoft.MinIoC -{ - /// - /// Inversion of control container handles dependency injection for registered types - /// - class Container : Container.IScope - { - #region Public interfaces - /// - /// Represents a scope in which per-scope objects are instantiated a single time - /// - public interface IScope : IDisposable, IServiceProvider - { - } - - /// - /// IRegisteredType is return by Container.Register and allows further configuration for the registration - /// - public interface IRegisteredType - { - /// - /// Make registered type a singleton - /// - void AsSingleton(); - - /// - /// Make registered type a per-scope type (single instance within a Scope) - /// - void PerScope(); - } - #endregion - - // Map of registered types - private readonly Dictionary> _registeredTypes = new Dictionary>(); - - // Lifetime management - private readonly ContainerLifetime _lifetime; - - /// - /// Creates a new instance of IoC Container - /// - public Container() => _lifetime = new ContainerLifetime(t => _registeredTypes[t]); - - /// - /// Registers a factory function which will be called to resolve the specified interface - /// - /// Interface to register - /// Factory function - /// - public IRegisteredType Register(Type @interface, Func factory) - => RegisterType(@interface, _ => factory()); - - /// - /// Registers an implementation type for the specified interface - /// - /// Interface to register - /// Implementing type - /// - public IRegisteredType Register(Type @interface, Type implementation) - => RegisterType(@interface, FactoryFromType(implementation)); - - private IRegisteredType RegisterType(Type itemType, Func factory) - => new RegisteredType(itemType, f => _registeredTypes[itemType] = f, factory); - - /// - /// Returns the object registered for the given type, if registered - /// - /// Type as registered with the container - /// Instance of the registered type, if registered; otherwise - public object GetService(Type type) - { - Func registeredType; - - if (!_registeredTypes.TryGetValue(type, out registeredType)) - { - return null; - } - - return registeredType(_lifetime); - } - - /// - /// Creates a new scope - /// - /// Scope object - public IScope CreateScope() => new ScopeLifetime(_lifetime); - - /// - /// Disposes any objects owned by this container. - /// - public void Dispose() => _lifetime.Dispose(); - - #region Lifetime management - // ILifetime management adds resolution strategies to an IScope - interface ILifetime : IScope - { - object GetServiceAsSingleton(Type type, Func factory); - - object GetServicePerScope(Type type, Func factory); - } - - // ObjectCache provides common caching logic for lifetimes - abstract class ObjectCache - { - // Instance cache - private readonly ConcurrentDictionary _instanceCache = new ConcurrentDictionary(); - - // Get from cache or create and cache object - protected object GetCached(Type type, Func factory, ILifetime lifetime) - => _instanceCache.GetOrAdd(type, _ => factory(lifetime)); - - public void Dispose() - { - foreach (var obj in _instanceCache.Values) - (obj as IDisposable)?.Dispose(); - } - } - - // Container lifetime management - class ContainerLifetime : ObjectCache, ILifetime - { - // Retrieves the factory functino from the given type, provided by owning container - public Func> GetFactory { get; private set; } - - public ContainerLifetime(Func> getFactory) => GetFactory = getFactory; - - public object GetService(Type type) => GetFactory(type)(this); - - // Singletons get cached per container - public object GetServiceAsSingleton(Type type, Func factory) - => GetCached(type, factory, this); - - // At container level, per-scope items are equivalent to singletons - public object GetServicePerScope(Type type, Func factory) - => GetServiceAsSingleton(type, factory); - } - - // Per-scope lifetime management - class ScopeLifetime : ObjectCache, ILifetime - { - // Singletons come from parent container's lifetime - private readonly ContainerLifetime _parentLifetime; - - public ScopeLifetime(ContainerLifetime parentContainer) => _parentLifetime = parentContainer; - - public object GetService(Type type) => _parentLifetime.GetFactory(type)(this); - - // Singleton resolution is delegated to parent lifetime - public object GetServiceAsSingleton(Type type, Func factory) - => _parentLifetime.GetServiceAsSingleton(type, factory); - - // Per-scope objects get cached - public object GetServicePerScope(Type type, Func factory) - => GetCached(type, factory, this); - } - #endregion - - #region Container items - // Compiles a lambda that calls the given type's first constructor resolving arguments - private static Func FactoryFromType(Type itemType) - { - // Get first constructor for the type - var constructors = itemType.GetConstructors(); - if (constructors.Length == 0) - { - // If no public constructor found, search for an internal constructor - constructors = itemType.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic); - } - var constructor = constructors.First(); - - // Compile constructor call as a lambda expression - var arg = Expression.Parameter(typeof(ILifetime)); - return (Func)Expression.Lambda( - Expression.New(constructor, constructor.GetParameters().Select( - param => - { - var resolve = new Func( - lifetime => lifetime.GetService(param.ParameterType)); - return Expression.Convert( - Expression.Call(Expression.Constant(resolve.Target), resolve.Method, arg), - param.ParameterType); - })), - arg).Compile(); - } - - // RegisteredType is supposed to be a short lived object tying an item to its container - // and allowing users to mark it as a singleton or per-scope item - class RegisteredType : IRegisteredType - { - private readonly Type _itemType; - private readonly Action> _registerFactory; - private readonly Func _factory; - - public RegisteredType(Type itemType, Action> registerFactory, Func factory) - { - _itemType = itemType; - _registerFactory = registerFactory; - _factory = factory; - - registerFactory(_factory); - } - - public void AsSingleton() - => _registerFactory(lifetime => lifetime.GetServiceAsSingleton(_itemType, _factory)); - - public void PerScope() - => _registerFactory(lifetime => lifetime.GetServicePerScope(_itemType, _factory)); - } - #endregion - } - - /// - /// Extension methods for Container - /// - static class ContainerExtensions - { - /// - /// Registers an implementation type for the specified interface - /// - /// Interface to register - /// This container instance - /// Implementing type - /// IRegisteredType object - public static Container.IRegisteredType Register(this Container container, Type type) - => container.Register(typeof(T), type); - - /// - /// Registers an implementation type for the specified interface - /// - /// Interface to register - /// Implementing type - /// This container instance - /// IRegisteredType object - public static Container.IRegisteredType Register(this Container container) - where TImplementation : TInterface - => container.Register(typeof(TInterface), typeof(TImplementation)); - - /// - /// Registers a factory function which will be called to resolve the specified interface - /// - /// Interface to register - /// This container instance - /// Factory method - /// IRegisteredType object - public static Container.IRegisteredType Register(this Container container, Func factory) - => container.Register(typeof(T), () => factory()); - - /// - /// Registers a type - /// - /// This container instance - /// Type to register - /// IRegisteredType object - public static Container.IRegisteredType Register(this Container container) - => container.Register(typeof(T), typeof(T)); - - /// - /// Returns an implementation of the specified interface - /// - /// Interface type - /// This scope instance - /// Object implementing the interface - public static T Resolve(this Container.IScope scope) => (T)scope.GetService(typeof(T)); - } -} \ No newline at end of file diff --git a/source/FFXIV.Framework/FFXIV.Framework/FFXIV.Framework.csproj b/source/FFXIV.Framework/FFXIV.Framework/FFXIV.Framework.csproj index 6a00578d..f1e78147 100644 --- a/source/FFXIV.Framework/FFXIV.Framework/FFXIV.Framework.csproj +++ b/source/FFXIV.Framework/FFXIV.Framework/FFXIV.Framework.csproj @@ -99,7 +99,6 @@ - From 080af2b04c14aa645ebfb7ed36845f52e4285629 Mon Sep 17 00:00:00 2001 From: bonbon Date: Sun, 11 Aug 2024 15:10:57 +0900 Subject: [PATCH 3/4] version up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 参照するFFXIV_ACT_PluginとAdvanced Combat Trackerを最新の物に更新した --- source/@MasterVersion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/@MasterVersion.txt b/source/@MasterVersion.txt index 99be913e..efcdd868 100644 --- a/source/@MasterVersion.txt +++ b/source/@MasterVersion.txt @@ -1 +1 @@ -v10.3.7 +v10.3.8 From a13ca879a49deebf7cdd803fb5c7e72d3a4ca2f6 Mon Sep 17 00:00:00 2001 From: bonbon Date: Sun, 11 Aug 2024 15:11:42 +0900 Subject: [PATCH 4/4] version up --- source/ACT.Hojoring.Common/Version.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/ACT.Hojoring.Common/Version.cs b/source/ACT.Hojoring.Common/Version.cs index 549aaac5..ff560dee 100644 --- a/source/ACT.Hojoring.Common/Version.cs +++ b/source/ACT.Hojoring.Common/Version.cs @@ -1,4 +1,4 @@ using System.Reflection; -[assembly: AssemblyVersion("10.3.0.7")] -[assembly: AssemblyFileVersion("10.3.0.7")] +[assembly: AssemblyVersion("10.3.0.8")] +[assembly: AssemblyFileVersion("10.3.0.8")]