diff --git a/src/BuiltIn/Selection/ArrayTypeSelector.cs b/src/BuiltIn/Selection/ArrayTypeSelector.cs new file mode 100644 index 000000000..fa7ab604a --- /dev/null +++ b/src/BuiltIn/Selection/ArrayTypeSelector.cs @@ -0,0 +1,44 @@ +using System; + +namespace Unity.BuiltIn +{ + public static class ArrayTypeSelector + + { + #region Selection + + public static Type Selector(UnityContainer container, Type argType) + { + Type? next; + Type? type = argType; + + do + { + if (type.IsGenericType) + { + if (container.Scope.Contains(type)) return type!; + + var definition = type.GetGenericTypeDefinition(); + if (container.Scope.Contains(definition)) return definition; + + next = type.GenericTypeArguments[0]!; + if (container.Scope.Contains(next)) return next; + } + else if (type.IsArray) + { + next = type.GetElementType()!; + if (container.Scope.Contains(next)) return next; + } + else + { + return type!; + } + } + while (null != (type = next)); + + return argType; + } + + #endregion + } +} diff --git a/src/Container/Processors/Constructor/Constructor.Selection.cs b/src/BuiltIn/Selection/ConstructorSelector.cs similarity index 78% rename from src/Container/Processors/Constructor/Constructor.Selection.cs rename to src/BuiltIn/Selection/ConstructorSelector.cs index fc56f52d9..199858b07 100644 --- a/src/Container/Processors/Constructor/Constructor.Selection.cs +++ b/src/BuiltIn/Selection/ConstructorSelector.cs @@ -3,20 +3,13 @@ using System.Linq; using System.Reflection; -namespace Unity.Container +namespace Unity.BuiltIn { - public partial class ConstructorProcessor + public static class ConstructorSelector { - #region Fields - - protected Func Select { get; set; } - - #endregion - - #region Selection - public ConstructorInfo? DefaultSelector(UnityContainer container, ConstructorInfo[] constructors) + public static ConstructorInfo? Selector(UnityContainer container, ConstructorInfo[] constructors) { Array.Sort(constructors, SortPredicate); @@ -37,7 +30,7 @@ public partial class ConstructorProcessor #region Implementation - protected bool CanResolve(UnityContainer container, ParameterInfo info) + private static bool CanResolve(UnityContainer container, ParameterInfo info) { // TODO: Add support for ImportMany var attribute = info.GetCustomAttribute(); @@ -48,7 +41,7 @@ protected bool CanResolve(UnityContainer container, ParameterInfo info) } // Sort Predicate - private int SortPredicate(ConstructorInfo x, ConstructorInfo y) + private static int SortPredicate(ConstructorInfo x, ConstructorInfo y) { int match; @@ -61,7 +54,7 @@ private int SortPredicate(ConstructorInfo x, ConstructorInfo y) return 0; } - private int RankByComplexity(ParameterInfo[] parameters) + private static int RankByComplexity(ParameterInfo[] parameters) { var sum = 0; foreach (var parameter in parameters) diff --git a/src/BuiltIn/Selection/MembersSelector.cs b/src/BuiltIn/Selection/MembersSelector.cs new file mode 100644 index 000000000..cada3682a --- /dev/null +++ b/src/BuiltIn/Selection/MembersSelector.cs @@ -0,0 +1,46 @@ +using System; +using System.Reflection; + +namespace Unity.BuiltIn +{ + public static class MembersSelector + { + #region Default Get Members + + /// + /// Determines constructors selected by default when + /// is called + /// + public static ConstructorInfo[] GetConstructors(Type type) + => type.GetConstructors(BindingFlags.Public | BindingFlags.Instance); + + + /// + /// Determines methods selected by default when + /// is called + /// + public static MethodInfo[] GetMethods(Type type) + => type.GetMethods(BindingFlags.Public | + BindingFlags.Instance | + BindingFlags.FlattenHierarchy | + BindingFlags.DeclaredOnly); + + + /// + /// Determines fields selected by default when + /// is called + /// + public static FieldInfo[] GetFields(Type type) + => type.GetFields(BindingFlags.Public | BindingFlags.Instance); + + + /// + /// Determines properties selected by default when + /// is called + /// + public static PropertyInfo[] GetProperties(Type type) + => type.GetProperties(BindingFlags.Public | BindingFlags.Instance); + + #endregion + } +} diff --git a/src/Container/Defaults/Defaults.Pipelines.cs b/src/Container/Defaults/Defaults.Pipelines.cs index e5b723c87..25cd00d22 100644 --- a/src/Container/Defaults/Defaults.Pipelines.cs +++ b/src/Container/Defaults/Defaults.Pipelines.cs @@ -52,8 +52,8 @@ public ResolveDelegate FactoryPipeline #region Arrays and Enumerable [DebuggerBrowsable(DebuggerBrowsableState.Never)] - public Func GerTargetType - => (Func)Data[GET_TARGET_TYPE].Value!; + public UnitySelector ArrayTargetType + => (UnitySelector)Data[GET_TARGET_TYPE].Value!; #endregion } diff --git a/src/Container/Defaults/Defaults.cs b/src/Container/Defaults/Defaults.cs index aca3cf123..0cf4988f6 100644 --- a/src/Container/Defaults/Defaults.cs +++ b/src/Container/Defaults/Defaults.cs @@ -51,7 +51,7 @@ internal Defaults() BUILD_PIPELINE_INSTANCE = Allocate>(); // Collections - GET_TARGET_TYPE = Allocate>(); + GET_TARGET_TYPE = Allocate>(); } #endregion diff --git a/src/Container/Processors/Constructor/Constructor.BuildUp.cs b/src/Container/Processors/Constructor/Constructor.BuildUp.cs index 9e1c78577..24bdbc5e5 100644 --- a/src/Container/Processors/Constructor/Constructor.BuildUp.cs +++ b/src/Container/Processors/Constructor/Constructor.BuildUp.cs @@ -69,7 +69,7 @@ public override void PreBuildUp(ref TContext context) /////////////////////////////////////////////////////////////////// // Select using algorithm - ConstructorInfo? info = Select(context.Container, members); + ConstructorInfo? info = SelectionHandler(context.Container, members); if (null != info) { using var action = context.Start(info); diff --git a/src/Container/Processors/Constructor/Constructor.Processor.cs b/src/Container/Processors/Constructor/Constructor.Processor.cs index d7aff29eb..34092e642 100644 --- a/src/Container/Processors/Constructor/Constructor.Processor.cs +++ b/src/Container/Processors/Constructor/Constructor.Processor.cs @@ -13,19 +13,25 @@ public partial class ConstructorProcessor : ParameterProcessor #endregion + #region Fields + + protected UnitySelector SelectionHandler { get; set; } + + #endregion + + #region Constructors public ConstructorProcessor(IPolicyObservable policies) : base(policies) { - Select = DefaultSelector; - policies.Set>(DefaultSelector, OnSelectorChanged); + SelectionHandler = policies.Get>(OnSelectorChanged)!; } private void OnSelectorChanged(Type? target, Type type, object? policy) { if (policy is null) throw new ArgumentNullException(nameof(policy)); - Select = (Func)policy; + SelectionHandler = (UnitySelector)policy; } #endregion diff --git a/src/Container/Processors/Member/Member.Processor.cs b/src/Container/Processors/Member/Member.Processor.cs index 29161cf29..9ce45374f 100644 --- a/src/Container/Processors/Member/Member.Processor.cs +++ b/src/Container/Processors/Member/Member.Processor.cs @@ -17,7 +17,7 @@ public abstract partial class MemberProcessor : /// This method returns an array of objects implemented /// by the /// - protected GetMembersDelegate GetSupportedMembers; + protected MembersSelector GetSupportedMembers; /// /// Function to load with data from current , @@ -32,7 +32,7 @@ public abstract partial class MemberProcessor : protected MemberProcessor(IPolicyObservable policies) { - GetSupportedMembers = policies.Get>(OnMembersSelectorChanged)!; + GetSupportedMembers = policies.Get>(OnMembersSelectorChanged)!; LoadImportInfo = policies.Get>(OnImportInfoLoaderChanged)!; } @@ -142,7 +142,7 @@ protected MemberProcessor(IPolicyObservable policies) } private void OnMembersSelectorChanged(Type? target, Type type, object? policy) - => GetSupportedMembers = (GetMembersDelegate)(policy ?? throw new ArgumentNullException(nameof(policy))); + => GetSupportedMembers = (MembersSelector)(policy ?? throw new ArgumentNullException(nameof(policy))); private void OnImportInfoLoaderChanged(Type? target, Type type, object? policy) => LoadImportInfo = (ImportProvider)(policy ?? throw new ArgumentNullException(nameof(policy))); diff --git a/src/Container/Unity/Resolution/Unity.Array.cs b/src/Container/Unity/Resolution/Unity.Array.cs index 7062b06f9..15ea61574 100644 --- a/src/Container/Unity/Resolution/Unity.Array.cs +++ b/src/Container/Unity/Resolution/Unity.Array.cs @@ -26,7 +26,7 @@ public partial class UnityContainer return context.Error($"Invalid array {type}. Only arrays of rank 1 are supported"); var element = type.GetElementType()!; - var target = Policies.GerTargetType(this, element!); + var target = Policies.ArrayTargetType(this, element!); var types = target.IsGenericType ? new[] { target, target.GetGenericTypeDefinition() } : new[] { target }; @@ -135,42 +135,5 @@ public partial class UnityContainer } #endregion - - - #region Target Type - - private static Type GetArrayTargetType(UnityContainer container, Type argType) - { - Type? next; - Type? type = argType; - - do - { - if (type.IsGenericType) - { - if (container.Scope.Contains(type)) return type!; - - var definition = type.GetGenericTypeDefinition(); - if (container.Scope.Contains(definition)) return definition; - - next = type.GenericTypeArguments[0]!; - if (container.Scope.Contains(next)) return next; - } - else if (type.IsArray) - { - next = type.GetElementType()!; - if (container.Scope.Contains(next)) return next; - } - else - { - return type!; - } - } - while (null != (type = next)); - - return argType; - } - - #endregion } } diff --git a/src/Container/Unity/Unity.cs b/src/Container/Unity/Unity.cs index ccb702a4f..79f30e821 100644 --- a/src/Container/Unity/Unity.cs +++ b/src/Container/Unity/Unity.cs @@ -32,7 +32,6 @@ public UnityContainer(string name, int capacity) Policies = new Defaults(); // TODO: Setup extension points - Policies.Set>(typeof(Array), GetArrayTargetType); Policies.Set>(typeof(IEnumerable<>), ResolveUnregisteredEnumerable); // Setup Scope diff --git a/src/Extension/Delegates/GetMembersDelegate.cs b/src/Extension/Delegates/MembersSelector.cs similarity index 92% rename from src/Extension/Delegates/GetMembersDelegate.cs rename to src/Extension/Delegates/MembersSelector.cs index c45c4611c..99c94e61a 100644 --- a/src/Extension/Delegates/GetMembersDelegate.cs +++ b/src/Extension/Delegates/MembersSelector.cs @@ -20,5 +20,5 @@ namespace Unity.Extension /// /// /// Array of supported members - public delegate TMemberInfo[] GetMembersDelegate(Type type); + public delegate TMemberInfo[] MembersSelector(Type type); } diff --git a/src/Extension/Delegates/UnitySelector.cs b/src/Extension/Delegates/UnitySelector.cs new file mode 100644 index 000000000..b2fae6d0b --- /dev/null +++ b/src/Extension/Delegates/UnitySelector.cs @@ -0,0 +1,15 @@ +using System; + +namespace Unity.Extension +{ + /// + /// The delegate to define selection handler that depends on the container's configuration + /// + /// of the input + /// of the output + /// Instance of the container + /// Value[s] to select from + /// Selected value + public delegate TOutput UnitySelector(UnityContainer container, TInput input); +} + diff --git a/src/Extension/Policy/IPolicy.Extensions.cs b/src/Extension/Policy/IPolicy.Extensions.cs index c48e5ff9d..6b6e2cd30 100644 --- a/src/Extension/Policy/IPolicy.Extensions.cs +++ b/src/Extension/Policy/IPolicy.Extensions.cs @@ -8,6 +8,15 @@ namespace Unity.Extension /// public static class PolicyExtensions { + #region Constants + + const string ERROR_NO_LOCAL = "This method is deprecated. Local policies are no longer supported"; + const string ERROR_NO_CASCADING = "This method is deprecated. Cascading policies are no longer supported"; + const string ERROR_NO_LOCAL_CASCADING = "This method is deprecated. Local, cascading policies are no longer supported"; + + #endregion + + #region Clear @@ -177,6 +186,17 @@ public static void Set(this IPolicyList policies, TPolicy policy) public static void Set(this IPolicyList policies, Type target, TPolicy policy) where TPolicy : class => policies.Set(target, typeof(TPolicy), policy); + /// + /// Sets a policy for a type + /// + /// The of the policy + /// The to register policy under + /// to add the policy to + /// The policy to be set + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Set(this IPolicyList policies, TPolicy policy) + where TPolicy : class => policies.Set(typeof(TTarget), typeof(TPolicy), policy); + /// /// Sets a default policy. When checking for a policy, if no specific individual policy /// is available, the default will be used. @@ -234,10 +254,63 @@ public static void Set(this IPolicyObservable policies, TPolicy policy, [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Set(this IPolicyObservable policies, Type target, TPolicy policy, PolicyChangeHandler handler) where TPolicy : class => policies.Set(target, typeof(TPolicy), policy, handler); - + + #endregion + + #endregion + #region Deprecated + + [Obsolete("This method is deprecated. Use 'Clear(Type policy)' instead", true)] + public static void Clear(this IPolicyList policies, object buildKey) + => throw new NotImplementedException(); + + [Obsolete("This method is deprecated. Use 'Get(Type policy)' instead", true)] + public static TPolicyInterface? Get(this IPolicyList policies, object buildKey) + => throw new NotImplementedException(); + + [Obsolete("This method is deprecated. Use 'Set(Type policy, TPolicyInterface instance)' instead", true)] + public static void Set(this IPolicyList policies, TPolicyInterface policy, object buildKey) + => throw new NotImplementedException(); + + [Obsolete("This method is deprecated. Use 'Get(Type? type, Type policy)' instead", true)] + public static object Get(this IPolicyList policies, Type policyInterface, object buildKey) + => throw new NotImplementedException(); + + [Obsolete(ERROR_NO_CASCADING, true)] + public static TPolicyInterface Get(this IPolicyList policies, object buildKey, out IPolicyList containingPolicyList) + => throw new NotImplementedException(); + + [Obsolete(ERROR_NO_CASCADING, true)] + public static object? Get(this IPolicyList policies, Type policyInterface, object buildKey, out IPolicyList containingPolicyList) + => throw new NotImplementedException(); + + [Obsolete(ERROR_NO_LOCAL, true)] + public static TPolicyInterface Get(this IPolicyList policies, object buildKey, bool localOnly) + => throw new NotImplementedException(); + + [Obsolete(ERROR_NO_LOCAL, true)] + public static object? Get(this IPolicyList policies, Type policyInterface, object buildKey, bool localOnly) + => throw new NotImplementedException(); + + [Obsolete(ERROR_NO_LOCAL, true)] + public static TPolicyInterface GetNoDefault(this IPolicyList policies, object buildKey, bool localOnly) + => throw new NotImplementedException(); + + [Obsolete(ERROR_NO_LOCAL, true)] + public static object? GetNoDefault(this IPolicyList policies, Type policyInterface, object buildKey, bool localOnly) + => throw new NotImplementedException(); + + [Obsolete(ERROR_NO_LOCAL_CASCADING, true)] + public static TPolicyInterface Get(this IPolicyList policies, object buildKey, bool localOnly, out IPolicyList containingPolicyList) + => throw new NotImplementedException(); + + [Obsolete(ERROR_NO_LOCAL_CASCADING, true)] + public static TPolicyInterface GetNoDefault(this IPolicyList policies, object buildKey, bool localOnly, out IPolicyList containingPolicyList) + => throw new NotImplementedException(); + #endregion } } diff --git a/src/Extension/Policy/IPolicyList.Deprecated.cs b/src/Extension/Policy/IPolicyList.Deprecated.cs deleted file mode 100644 index 0b5efe9e7..000000000 --- a/src/Extension/Policy/IPolicyList.Deprecated.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; - -namespace Unity.Extension -{ - /// - /// Deprecated extension methods on - /// - public static class PolicyListDeprecated - { - #region Constants - - const string ERROR_NO_LOCAL = "This method is deprecated. Local policies are no longer supported"; - const string ERROR_NO_CASCADING = "This method is deprecated. Cascading policies are no longer supported"; - const string ERROR_NO_LOCAL_CASCADING = "This method is deprecated. Local, cascading policies are no longer supported"; - - #endregion - - - [Obsolete("This method is deprecated. Use 'Clear(Type policy)' instead", true)] - public static void Clear(this IPolicyList policies, object buildKey) - => throw new NotImplementedException(); - - [Obsolete("This method is deprecated. Use 'Get(Type policy)' instead", true)] - public static TPolicyInterface? Get(this IPolicyList policies, object buildKey) - => throw new NotImplementedException(); - - [Obsolete("This method is deprecated. Use 'Set(Type policy, TPolicyInterface instance)' instead", true)] - public static void Set(this IPolicyList policies, TPolicyInterface policy, object buildKey) - => throw new NotImplementedException(); - - [Obsolete("This method is deprecated. Use 'Get(Type? type, Type policy)' instead", true)] - public static object Get(this IPolicyList policies, Type policyInterface, object buildKey) - => throw new NotImplementedException(); - - [Obsolete(ERROR_NO_CASCADING, true)] - public static TPolicyInterface Get(this IPolicyList policies, object buildKey, out IPolicyList containingPolicyList) - => throw new NotImplementedException(); - - [Obsolete(ERROR_NO_CASCADING, true)] - public static object? Get(this IPolicyList policies, Type policyInterface, object buildKey, out IPolicyList containingPolicyList) - => throw new NotImplementedException(); - - [Obsolete(ERROR_NO_LOCAL, true)] - public static TPolicyInterface Get(this IPolicyList policies, object buildKey, bool localOnly) - => throw new NotImplementedException(); - - [Obsolete(ERROR_NO_LOCAL, true)] - public static object? Get(this IPolicyList policies, Type policyInterface, object buildKey, bool localOnly) - => throw new NotImplementedException(); - - [Obsolete(ERROR_NO_LOCAL, true)] - public static TPolicyInterface GetNoDefault(this IPolicyList policies, object buildKey, bool localOnly) - => throw new NotImplementedException(); - - [Obsolete(ERROR_NO_LOCAL, true)] - public static object? GetNoDefault(this IPolicyList policies, Type policyInterface, object buildKey, bool localOnly) - => throw new NotImplementedException(); - - [Obsolete(ERROR_NO_LOCAL_CASCADING, true)] - public static TPolicyInterface Get(this IPolicyList policies, object buildKey, bool localOnly, out IPolicyList containingPolicyList) - => throw new NotImplementedException(); - - [Obsolete(ERROR_NO_LOCAL_CASCADING, true)] - public static TPolicyInterface GetNoDefault(this IPolicyList policies, object buildKey, bool localOnly, out IPolicyList containingPolicyList) - => throw new NotImplementedException(); - } -} diff --git a/src/Extension/UnityDefaultBehaviorExtension.cs b/src/Extension/UnityDefaultBehaviorExtension.cs index f359c0eac..e320625ce 100644 --- a/src/Extension/UnityDefaultBehaviorExtension.cs +++ b/src/Extension/UnityDefaultBehaviorExtension.cs @@ -1,5 +1,6 @@ using System; using System.Reflection; +using Unity.BuiltIn; namespace Unity.Extension { @@ -14,13 +15,17 @@ public class UnityDefaultBehaviorExtension /// public static void Initialize(ExtensionContext context) { - // Set Member Selectors: GetConstructors(), GetFields(), etc. - context.Policies.Set>(GetConstructors); - context.Policies.Set>(GetProperties); - context.Policies.Set>(GetMethods); - context.Policies.Set>(GetFields); + // Array Target type selector + context.Policies.Set>(ArrayTypeSelector.Selector); + + // Set Constructor selector + context.Policies.Set>(ConstructorSelector.Selector); - // TODO: Set default Constructor selector + // Set Member Selectors: GetConstructors(), GetFields(), etc. + context.Policies.Set>(MembersSelector.GetConstructors); + context.Policies.Set>(MembersSelector.GetProperties); + context.Policies.Set>(MembersSelector.GetMethods); + context.Policies.Set>(MembersSelector.GetFields); #region Factories @@ -30,44 +35,5 @@ public static void Initialize(ExtensionContext context) #endregion } - - - #region Default Get Members - - /// - /// Determines constructors selected by default when - /// is called - /// - public static ConstructorInfo[] GetConstructors(Type type) - => type.GetConstructors(BindingFlags.Public | BindingFlags.Instance); - - - /// - /// Determines methods selected by default when - /// is called - /// - public static MethodInfo[] GetMethods(Type type) - => type.GetMethods(BindingFlags.Public | - BindingFlags.Instance | - BindingFlags.FlattenHierarchy | - BindingFlags.DeclaredOnly); - - - /// - /// Determines fields selected by default when - /// is called - /// - public static FieldInfo[] GetFields(Type type) - => type.GetFields(BindingFlags.Public | BindingFlags.Instance); - - - /// - /// Determines properties selected by default when - /// is called - /// - public static PropertyInfo[] GetProperties(Type type) - => type.GetProperties(BindingFlags.Public | BindingFlags.Instance); - - #endregion } }