Skip to content

Commit

Permalink
- Added RegisterSingleton extension methods
Browse files Browse the repository at this point in the history
- Added InjectionConstructor(Type[] args) selector
  • Loading branch information
ENikS committed Nov 8, 2017
1 parent 22a7542 commit 6b839e5
Show file tree
Hide file tree
Showing 3 changed files with 241 additions and 59 deletions.
2 changes: 1 addition & 1 deletion package.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>

<PropertyGroup>
<Version>2.1.1</Version>
<Version>2.1.2</Version>
<PackageReleaseNotes>This package is distributed as .NET Standard 1.0, 2.0, .Net Core 1.0 and .NET 4.0, 4.5, 4.7</PackageReleaseNotes>
</PropertyGroup>

Expand Down
79 changes: 64 additions & 15 deletions src/Injection/InjectionConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Globalization;
using System.Linq;
using System.Reflection;
using Unity.Attributes;
using Unity.Builder;
using Unity.Builder.Policy;
using Unity.Policy;
Expand All @@ -20,7 +21,7 @@ namespace Unity.Injection
/// </summary>
public class InjectionConstructor : InjectionMember
{
private readonly object[] _data;
private readonly InjectionParameterValue[] _data;
private readonly Type[] _types;

/// <summary>
Expand All @@ -29,8 +30,6 @@ public class InjectionConstructor : InjectionMember
/// </summary>
public InjectionConstructor()
{
_data = new object[0];
_types = new Type[0];
}

/// <summary>
Expand All @@ -51,8 +50,9 @@ public InjectionConstructor(params Type[] types)
/// be converted to <see cref="InjectionParameterValue"/> objects.</param>
public InjectionConstructor(params object[] parameterValues)
{
_data = parameterValues ?? throw new ArgumentNullException(nameof(parameterValues));
_types = _data.Select(o => o.GetType()).ToArray();
_data = (parameterValues ?? throw new ArgumentNullException(nameof(parameterValues)))
.Select(InjectionParameterValue.ToParameter)
.ToArray();
}

/// <summary>
Expand All @@ -65,28 +65,77 @@ public InjectionConstructor(params object[] parameterValues)
/// <param name="policies">Policy list to add policies to.</param>
public override void AddPolicies(Type serviceType, Type implementationType, string name, IPolicyList policies)
{
ConstructorInfo ctor = FindConstructor(implementationType);
var policy = null != _data ? ConstructorByArguments(implementationType, _data) :
null != _types ? ConstructorByType(implementationType, _types) :
DefaultConstructor(implementationType);

var values = null == _data ? null : InjectionParameterValue.ToParameters(_data).ToArray();
policies.Set<IConstructorSelectorPolicy>(new SpecifiedConstructorSelectorPolicy(ctor, values),
new NamedTypeBuildKey(implementationType, name));
policies.Set<IConstructorSelectorPolicy>(policy, new NamedTypeBuildKey(implementationType, name));
}

private ConstructorInfo FindConstructor(Type typeToCreate)
private SpecifiedConstructorSelectorPolicy DefaultConstructor(Type typeToCreate)
{
foreach (var ctor in typeToCreate.GetTypeInfo()
.DeclaredConstructors
.Where(c => c.IsStatic == false && c.IsPublic))
{
if (ctor.GetParameters().ParametersMatch(_types))
return ctor;
if (!ctor.GetParameters().Select(p => p.ParameterType).Any())
{
return new SpecifiedConstructorSelectorPolicy(ctor, new InjectionParameterValue[0]);
}
}

var values = null != _data ? InjectionParameterValue.ToParameters(_data).Select(p => p.ParameterTypeName).ToArray()
: _types.Select(t => t.Name) ;
throw new InvalidOperationException(
string.Format(CultureInfo.CurrentCulture,
Constants.NoSuchConstructor,
typeToCreate.FullName, string.Empty));
}


private SpecifiedConstructorSelectorPolicy ConstructorByArguments(Type typeToCreate, InjectionParameterValue[] data)
{
foreach (var ctor in typeToCreate.GetTypeInfo()
.DeclaredConstructors
.Where(c => c.IsStatic == false && c.IsPublic))
{
if (_data.Matches(ctor.GetParameters().Select(p => p.ParameterType)))
{
return new SpecifiedConstructorSelectorPolicy(ctor, data);
}
}

string signature = string.Join(", ", data.Select(p => p.ParameterTypeName).ToArray());

throw new InvalidOperationException(
string.Format(CultureInfo.CurrentCulture,
Constants.NoSuchConstructor,
typeToCreate.FullName,
signature));
}

private SpecifiedConstructorSelectorPolicy ConstructorByType(Type typeToCreate, Type[] types)
{
foreach (var ctor in typeToCreate.GetTypeInfo()
.DeclaredConstructors
.Where(c => c.IsStatic == false && c.IsPublic))
{
var parameters = ctor.GetParameters();
if (parameters.ParametersMatch(types))
{
return new SpecifiedConstructorSelectorPolicy(ctor, parameters.Select(ToResolvedParameter)
.ToArray());
}
}

throw new InvalidOperationException(
string.Format(CultureInfo.CurrentCulture, Constants.NoSuchConstructor, typeToCreate.FullName, string.Join(", ", values)));
string.Format(CultureInfo.CurrentCulture, Constants.NoSuchConstructor,
typeToCreate.FullName, string.Join(", ", _types.Select(t => t.Name))));
}

private InjectionParameterValue ToResolvedParameter(ParameterInfo parameter)
{
return new ResolvedParameter(parameter.ParameterType, parameter.GetCustomAttributes(false)
.OfType<DependencyAttribute>()
.FirstOrDefault()?.Name);
}
}
}
Loading

0 comments on commit 6b839e5

Please sign in to comment.