Skip to content

Commit

Permalink
Improving GenericParameter and OptionalGenericParameter injection par…
Browse files Browse the repository at this point in the history
…ameters

Fixed #294
  • Loading branch information
ENikS committed Dec 5, 2020
1 parent f6d30e7 commit bba898f
Show file tree
Hide file tree
Showing 13 changed files with 137 additions and 25 deletions.
17 changes: 16 additions & 1 deletion src/Container/Processors/Member/Member.Activation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,23 @@ public override void PreBuild(ref PipelineContext context)
// Injection, if exists
while (null != injection)
{
if (MatchRank.ExactMatch == injection.Match(Unsafe.As<TMemberInfo>(import.MemberInfo)))
var match = injection.Match(Unsafe.As<TMemberInfo>(import.MemberInfo));

if (MatchRank.NoMatch != match)
{
if (MatchRank.ExactMatch != match)
{
match = injection.Data is IMatch<TMemberInfo> iMatch
? iMatch.Match(Unsafe.As<TMemberInfo>(import.MemberInfo))
: injection.Data.MatchTo(import.MemberType);

if (MatchRank.NoMatch == match)
{
context.Error($"{injection.Data} is not compatible with {import.MemberInfo}");
return;
}
}

injection.GetImportInfo(ref import);
goto activate;
}
Expand Down
10 changes: 10 additions & 0 deletions src/Dependency/Injection/Members/Injection.Field.Optional.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace Unity.Injection
{
Expand Down Expand Up @@ -33,5 +34,14 @@ public OptionalField(string fieldName, object value)
}

#endregion


#region Implementation

[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected override Type GetMemberType(FieldInfo member)
=> member.FieldType;

#endregion
}
}
10 changes: 10 additions & 0 deletions src/Dependency/Injection/Members/Injection.Field.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace Unity.Injection
{
Expand Down Expand Up @@ -55,5 +56,14 @@ public InjectionField(string fieldName, object value)
}

#endregion


#region Implementation

[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected override Type GetMemberType(FieldInfo member)
=> member.FieldType;

#endregion
}
}
6 changes: 3 additions & 3 deletions src/Dependency/Injection/Members/Injection.Member.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ public abstract class InjectionMember
public InjectionMember? Next { get; internal set; }
}

public abstract class InjectionMember<TMemberInfo, TData> : InjectionMember, IMatch<TMemberInfo>,
public abstract class InjectionMember<TMemberInfo, TData> : InjectionMember,
IMatch<TMemberInfo>,
IInjectionProvider
where TMemberInfo : MemberInfo
where TData : class
Expand Down Expand Up @@ -61,8 +62,7 @@ protected InjectionMember(string name, TData data)

[MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <inheritdoc/>
public virtual MatchRank Match(TMemberInfo other)
=> other.Name == Name ? MatchRank.ExactMatch : MatchRank.NoMatch;
public abstract MatchRank Match(TMemberInfo other);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <inheritdoc/>
Expand Down
35 changes: 24 additions & 11 deletions src/Dependency/Injection/Members/Injection.MemberInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace Unity.Injection
{
Expand All @@ -8,8 +9,8 @@ public abstract class InjectionMemberInfo<TMemberInfo> : InjectionMember<TMember
{
#region Fields

private readonly Type? _type;
private readonly string? _name;
private readonly Type? _contractType;
private readonly string? _contractName;
private readonly bool _optional;

#endregion
Expand All @@ -20,37 +21,37 @@ public abstract class InjectionMemberInfo<TMemberInfo> : InjectionMember<TMember
protected InjectionMemberInfo(string member, object data, bool optional)
: base(member, data)
{
_name = Contract.AnyContractName;
_contractName = Contract.AnyContractName;
_optional = optional;
}

protected InjectionMemberInfo(string member, bool optional)
: base(member, RegistrationManager.NoValue)
{
_name = Contract.AnyContractName;
_contractName = Contract.AnyContractName;
_optional = optional;
}

protected InjectionMemberInfo(string member, Type contractType, bool optional)
: base(member, RegistrationManager.NoValue)
{
_type = contractType;
_name = Contract.AnyContractName;
_contractType = contractType;
_contractName = Contract.AnyContractName;
_optional = optional;
}

protected InjectionMemberInfo(string member, string? contractName, bool optional)
: base(member, RegistrationManager.NoValue)
{
_name = contractName;
_contractName = contractName;
_optional = optional;
}

protected InjectionMemberInfo(string member, Type contractType, string? contractName, bool optional)
: base(member, RegistrationManager.NoValue)
{
_type = contractType;
_name = contractName;
_contractType = contractType;
_contractName = contractName;
_optional = optional;
}

Expand All @@ -59,6 +60,18 @@ protected InjectionMemberInfo(string member, Type contractType, string? contract

#region Implementation

[MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <inheritdoc/>
public override MatchRank Match(TMemberInfo other)
=> other.Name != Name
? MatchRank.NoMatch
: ReferenceEquals(Data, RegistrationManager.NoValue)
? MatchRank.ExactMatch
: MatchRank.Compatible;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected abstract Type GetMemberType(TMemberInfo member);

public override void GetImportInfo<TImport>(ref TImport import)
{
if (Data is IInjectionProvider provider)
Expand All @@ -77,10 +90,10 @@ public override void GetImportInfo<TImport>(ref TImport import)
return;
}

if (null != _type) import.ContractType = _type;
if (null != _contractType) import.ContractType = _contractType;

// Name
if (!ReferenceEquals(_name, Contract.AnyContractName)) import.ContractName = _name;
if (!ReferenceEquals(_contractName, Contract.AnyContractName)) import.ContractName = _contractName;

// Data
if (!ReferenceEquals(RegistrationManager.NoValue, Data)) import.External = Data;
Expand Down
4 changes: 4 additions & 0 deletions src/Dependency/Injection/Members/Injection.MethodBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ protected InjectionMethodBase(string name, params object[] arguments)

#region Matching

public override MatchRank Match(TMemberInfo other)
=> throw new System.NotImplementedException();

public abstract int SelectFrom(TMemberInfo[] members);

// TODO: Integrate with match
public int CompareTo(TMemberInfo? other)
{
System.Diagnostics.Debug.Assert(null != other);
Expand Down
10 changes: 10 additions & 0 deletions src/Dependency/Injection/Members/Injection.Property.Optional.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace Unity.Injection
{
Expand Down Expand Up @@ -37,5 +38,14 @@ public OptionalProperty(string propertyName, object value)
}

#endregion


#region Implementation

[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected override Type GetMemberType(PropertyInfo member)
=> member.PropertyType;

#endregion
}
}
10 changes: 10 additions & 0 deletions src/Dependency/Injection/Members/Injection.Property.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace Unity.Injection
{
Expand Down Expand Up @@ -35,5 +36,14 @@ public InjectionProperty(string propertyName, object value)
}

#endregion


#region Implementation

[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected override Type GetMemberType(PropertyInfo member)
=> member.PropertyType;

#endregion
}
}
42 changes: 38 additions & 4 deletions src/Dependency/Injection/Parameters/Parameter.Base.Generic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ namespace Unity.Injection
/// <summary>
/// Base class for generic type parameters.
/// </summary>
public abstract class GenericParameterBase : ParameterValue
public abstract class GenericParameterBase : ParameterValue,
IMatch<FieldInfo>,
IMatch<PropertyInfo>
{
#region Fields

Expand Down Expand Up @@ -63,19 +65,50 @@ protected GenericParameterBase(string genericParameterName, string? contractName

#region IMatch

public virtual MatchRank Match(FieldInfo field)
{
if (!field.DeclaringType!.IsGenericType)
return MatchRank.NoMatch;

var type = field.DeclaringType?
.GetGenericTypeDefinition()
.GetField(field.Name)?
.FieldType;

return type is null
? MatchRank.NoMatch
: Match(type);
}

public virtual MatchRank Match(PropertyInfo property)
{
if (!property.DeclaringType!.IsGenericType)
return MatchRank.NoMatch;

var type = property.DeclaringType?
.GetGenericTypeDefinition()
.GetProperty(property.Name)?
.PropertyType;
return type is null
? MatchRank.NoMatch
: Match(type);
}

public override MatchRank Match(ParameterInfo parameter)
{
if (!parameter.Member.DeclaringType!.IsGenericType)
return MatchRank.NoMatch;

var definition = parameter.Member.DeclaringType!.GetGenericTypeDefinition();
var type = MethodBase.GetMethodFromHandle(((MethodBase)parameter.Member).MethodHandle, definition.TypeHandle)!
var type = MethodBase.GetMethodFromHandle(((MethodBase)parameter.Member).MethodHandle, definition.TypeHandle)?
.GetParameters()[parameter.Position]
.ParameterType;
return Match(type);
return type is null
? MatchRank.NoMatch
: Match(type);
}

public virtual MatchRank Match(Type type)
public override MatchRank Match(Type type)
{
if (false == _isArray)
return type.IsGenericParameter && type.Name == _genericParameterName
Expand Down Expand Up @@ -103,6 +136,7 @@ public override void GetImportInfo<TImport>(ref TImport import)
import.AllowDefault = AllowDefault;
}


#endregion
}
}
4 changes: 2 additions & 2 deletions src/Dependency/Injection/Parameters/Parameter.Base.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ protected ParameterBase(Type? importedType, bool optional)

#region Match

public override MatchRank Match(ParameterInfo parameter)
public override MatchRank Match(Type type)
{
return ParameterType is null
? MatchRank.ExactMatch
: ParameterType.MatchTo(parameter.ParameterType);
: ParameterType.MatchTo(type);
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class OptionalGenericParameter : GenericParameterBase
/// </summary>
/// <param name="genericParameterName">Name to the generic parameter</param>
public OptionalGenericParameter(string genericParameterName)
: base(genericParameterName, null, true)
: base(genericParameterName, Contract.AnyContractName, true)
{ }

/// <summary>
Expand Down
11 changes: 8 additions & 3 deletions src/Dependency/Injection/Parameters/Parameter.Value.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Reflection;
using System;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace Unity.Injection
Expand All @@ -8,7 +9,8 @@ namespace Unity.Injection
/// constructor or method injection, or for getting the value to
/// be injected into a property.
/// </summary>
public abstract class ParameterValue : IInjectionProvider,
public abstract class ParameterValue : IMatch<Type>,
IInjectionProvider,
IMatch<ParameterInfo>
{
#region IInjectionProvider
Expand All @@ -28,7 +30,10 @@ public abstract void GetImportInfo<TImport>(ref TImport import)
/// </summary>
/// <param name="other"><see cref="ParameterInfo"/> to compare to</param>
/// <returns>True if <see cref="ParameterInfo"/> is compatible</returns>
public abstract MatchRank Match(ParameterInfo parameter);
public virtual MatchRank Match(ParameterInfo parameter)
=> Match(parameter.ParameterType);

public abstract MatchRank Match(Type type);

#endregion
}
Expand Down
1 change: 1 addition & 0 deletions src/Dependency/Matching/Matching.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public static MatchRank MatchTo(this object value, ParameterInfo parameter)
? MatchRank.Compatible : MatchRank.NoMatch;
}


public static MatchRank MatchTo(this Array array, Type target)
{
var type = array.GetType();
Expand Down

0 comments on commit bba898f

Please sign in to comment.