Skip to content

Commit

Permalink
wip: Defaults
Browse files Browse the repository at this point in the history
Issue #301
  • Loading branch information
ENikS committed Dec 24, 2020
1 parent 0a7099d commit 0cdb50c
Show file tree
Hide file tree
Showing 15 changed files with 214 additions and 176 deletions.
44 changes: 44 additions & 0 deletions src/BuiltIn/Selection/ArrayTypeSelector.cs
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<UnityContainer, ConstructorInfo[], ConstructorInfo?> 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);

Expand All @@ -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<ImportAttribute>();
Expand All @@ -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;

Expand All @@ -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)
Expand Down
46 changes: 46 additions & 0 deletions src/BuiltIn/Selection/MembersSelector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Reflection;

namespace Unity.BuiltIn
{
public static class MembersSelector
{
#region Default Get Members

/// <summary>
/// Determines constructors selected by default when
/// <see cref="Type.GetConstructors"/> is called
/// </summary>
public static ConstructorInfo[] GetConstructors(Type type)
=> type.GetConstructors(BindingFlags.Public | BindingFlags.Instance);


/// <summary>
/// Determines methods selected by default when
/// <see cref="Type.GetMethods"/> is called
/// </summary>
public static MethodInfo[] GetMethods(Type type)
=> type.GetMethods(BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.FlattenHierarchy |
BindingFlags.DeclaredOnly);


/// <summary>
/// Determines fields selected by default when
/// <see cref="Type.GetFields"/> is called
/// </summary>
public static FieldInfo[] GetFields(Type type)
=> type.GetFields(BindingFlags.Public | BindingFlags.Instance);


/// <summary>
/// Determines properties selected by default when
/// <see cref="Type.GetProperties"/> is called
/// </summary>
public static PropertyInfo[] GetProperties(Type type)
=> type.GetProperties(BindingFlags.Public | BindingFlags.Instance);

#endregion
}
}
4 changes: 2 additions & 2 deletions src/Container/Defaults/Defaults.Pipelines.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ public ResolveDelegate<PipelineContext> FactoryPipeline
#region Arrays and Enumerable

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public Func<UnityContainer, Type, Type> GerTargetType
=> (Func<UnityContainer, Type, Type>)Data[GET_TARGET_TYPE].Value!;
public UnitySelector<Type, Type> ArrayTargetType
=> (UnitySelector<Type, Type>)Data[GET_TARGET_TYPE].Value!;

#endregion
}
Expand Down
2 changes: 1 addition & 1 deletion src/Container/Defaults/Defaults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ internal Defaults()
BUILD_PIPELINE_INSTANCE = Allocate<CategoryInstance, ResolveDelegate<PipelineContext>>();

// Collections
GET_TARGET_TYPE = Allocate<Array, Func<UnityContainer, Type, Type>>();
GET_TARGET_TYPE = Allocate<Array, UnitySelector<Type, Type>>();
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public override void PreBuildUp<TContext>(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);
Expand Down
12 changes: 9 additions & 3 deletions src/Container/Processors/Constructor/Constructor.Processor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,25 @@ public partial class ConstructorProcessor : ParameterProcessor<ConstructorInfo>
#endregion


#region Fields

protected UnitySelector<ConstructorInfo[], ConstructorInfo?> SelectionHandler { get; set; }

#endregion


#region Constructors

public ConstructorProcessor(IPolicyObservable policies)
: base(policies)
{
Select = DefaultSelector;
policies.Set<Func<UnityContainer, ConstructorInfo[], ConstructorInfo?>>(DefaultSelector, OnSelectorChanged);
SelectionHandler = policies.Get<ConstructorInfo, UnitySelector<ConstructorInfo[], ConstructorInfo?>>(OnSelectorChanged)!;
}

private void OnSelectorChanged(Type? target, Type type, object? policy)
{
if (policy is null) throw new ArgumentNullException(nameof(policy));
Select = (Func<UnityContainer, ConstructorInfo[], ConstructorInfo?>)policy;
SelectionHandler = (UnitySelector<ConstructorInfo[], ConstructorInfo?>)policy;
}

#endregion
Expand Down
6 changes: 3 additions & 3 deletions src/Container/Processors/Member/Member.Processor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public abstract partial class MemberProcessor<TMemberInfo, TDependency, TData> :
/// This method returns an array of <see cref="MemberInfo"/> objects implemented
/// by the <see cref="Type"/>
/// </summary>
protected GetMembersDelegate<TMemberInfo> GetSupportedMembers;
protected MembersSelector<TMemberInfo> GetSupportedMembers;

/// <summary>
/// Function to load <see cref="ImportInfo{TMember}"/> with data from current <see cref="ParameterInfo"/>,
Expand All @@ -32,7 +32,7 @@ public abstract partial class MemberProcessor<TMemberInfo, TDependency, TData> :

protected MemberProcessor(IPolicyObservable policies)
{
GetSupportedMembers = policies.Get<GetMembersDelegate<TMemberInfo>>(OnMembersSelectorChanged)!;
GetSupportedMembers = policies.Get<TMemberInfo, MembersSelector<TMemberInfo>>(OnMembersSelectorChanged)!;
LoadImportInfo = policies.Get<TDependency, ImportProvider<ImportInfo, ImportType>>(OnImportInfoLoaderChanged)!;
}

Expand Down Expand Up @@ -142,7 +142,7 @@ protected MemberProcessor(IPolicyObservable policies)
}

private void OnMembersSelectorChanged(Type? target, Type type, object? policy)
=> GetSupportedMembers = (GetMembersDelegate<TMemberInfo>)(policy ?? throw new ArgumentNullException(nameof(policy)));
=> GetSupportedMembers = (MembersSelector<TMemberInfo>)(policy ?? throw new ArgumentNullException(nameof(policy)));

private void OnImportInfoLoaderChanged(Type? target, Type type, object? policy)
=> LoadImportInfo = (ImportProvider<ImportInfo, ImportType>)(policy ?? throw new ArgumentNullException(nameof(policy)));
Expand Down
39 changes: 1 addition & 38 deletions src/Container/Unity/Resolution/Unity.Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down Expand Up @@ -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
}
}
1 change: 0 additions & 1 deletion src/Container/Unity/Unity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ public UnityContainer(string name, int capacity)
Policies = new Defaults();

// TODO: Setup extension points
Policies.Set<Func<UnityContainer, Type, Type>>(typeof(Array), GetArrayTargetType);
Policies.Set<ResolverFactory<PipelineContext>>(typeof(IEnumerable<>), ResolveUnregisteredEnumerable);

// Setup Scope
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ namespace Unity.Extension
/// </code>
/// </example>
/// <returns>Array of supported members</returns>
public delegate TMemberInfo[] GetMembersDelegate<TMemberInfo>(Type type);
public delegate TMemberInfo[] MembersSelector<TMemberInfo>(Type type);
}
15 changes: 15 additions & 0 deletions src/Extension/Delegates/UnitySelector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;

namespace Unity.Extension
{
/// <summary>
/// The delegate to define selection handler that depends on the container's configuration
/// </summary>
/// <typeparam name="TInput"><see cref="Type"/> of the input</typeparam>
/// <typeparam name="TOutput"><see cref="Type"/> of the output</typeparam>
/// <param name="container">Instance of the container</param>
/// <param name="input">Value[s] to select from</param>
/// <returns>Selected value</returns>
public delegate TOutput UnitySelector<in TInput, out TOutput>(UnityContainer container, TInput input);
}

Loading

0 comments on commit 0cdb50c

Please sign in to comment.