Skip to content
This repository has been archived by the owner on Oct 20, 2023. It is now read-only.

Commit

Permalink
Merge pull request #84 from Barsonax/feature/removenetframework
Browse files Browse the repository at this point in the history
removed netframework, added expression based API for property injection
  • Loading branch information
Barsonax authored Jul 6, 2019
2 parents b9e694d + 01d1029 commit 10fa667
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net452</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Singularity.Duality.Examples.core</AssemblyName>
<NoWarn>1701;1702;1705;1591;NU1701</NoWarn>
<IsPackable>false</IsPackable>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net452;netstandard2.0</TargetFrameworks>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Singularity.Duality.core</AssemblyName>
<PackageProjectUrl>https://github.com/Barsonax/Singularity</PackageProjectUrl>
<PackageIconUrl>https://raw.githubusercontent.com/Barsonax/Singularity/master/Icon.png</PackageIconUrl>
Expand Down
5 changes: 3 additions & 2 deletions src/Singularity/Container.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,10 @@ private Action<Scoped, object> GenerateLateInjector(Type type)
body.Add(Expression.Call(instanceCasted, methodInfo, parameterExpressions));
}

foreach (PropertyInfo propertyInfo in lateInjectorBindings.SelectMany(x => x.InjectionProperties))
foreach (MemberInfo memberInfo in lateInjectorBindings.SelectMany(x => x.InjectionProperties))
{
body.Add(Expression.Assign(Expression.MakeMemberAccess(instanceCasted, propertyInfo), _dependencyGraph.Resolve(propertyInfo.PropertyType).Context.Expression));
MemberExpression memberAccessExpression = Expression.MakeMemberAccess(instanceCasted, memberInfo);
body.Add(Expression.Assign(memberAccessExpression, _dependencyGraph.Resolve(memberAccessExpression.Type).Context.Expression));
}

if (body.Count == 0) return (scope, instance) => { };
Expand Down
4 changes: 2 additions & 2 deletions src/Singularity/Registration/LateInjectorBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ internal sealed class LateInjectorBinding
{
public Type InstanceType { get; }
public ArrayList<MethodInfo> InjectionMethods { get; }
public ArrayList<PropertyInfo> InjectionProperties { get; }
public ArrayList<MemberInfo> InjectionProperties { get; }
public BindingMetadata BindingMetadata { get; }

public LateInjectorBinding(Type instanceType, BindingMetadata bindingMetadata, ArrayList<MethodInfo> injectionMethods, ArrayList<PropertyInfo> injectionProperties)
public LateInjectorBinding(Type instanceType, BindingMetadata bindingMetadata, ArrayList<MethodInfo> injectionMethods, ArrayList<MemberInfo> injectionProperties)
{
InstanceType = instanceType;
InjectionMethods = injectionMethods;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Linq;
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Singularity.Collections;
using Singularity.Graph;
Expand All @@ -13,7 +15,7 @@ public sealed class StronglyTypedLateInjectorConfigurator<TInstance>
{
private readonly BindingMetadata _bindingMetadata;
private readonly ArrayList<MethodInfo> _injectionMethods = new ArrayList<MethodInfo>();
private readonly ArrayList<PropertyInfo> _injectionProperties = new ArrayList<PropertyInfo>();
private readonly ArrayList<MemberInfo> _injectionMembers = new ArrayList<MemberInfo>();

internal StronglyTypedLateInjectorConfigurator(BindingMetadata bindingMetadata)
{
Expand Down Expand Up @@ -46,33 +48,82 @@ public StronglyTypedLateInjectorConfigurator<TInstance> UseMethod(MethodInfo met
}

/// <summary>
/// Searches for a property with a public setter that matches the provided <paramref name="propertyName"/> and registers it as a target for property injection.
/// Registers a member for injection using a strongly typed expression.
/// </summary>
/// <param name="expression"></param>
/// <returns></returns>
public StronglyTypedLateInjectorConfigurator<TInstance> UseMember(Expression<Func<TInstance, object>> expression)
{
switch (expression.Body)
{
case MemberExpression memberExpression:
switch (memberExpression.Member)
{
case PropertyInfo propertyInfo:
return UseProperty(propertyInfo);
case FieldInfo fieldInfo:
return UseField(fieldInfo);
default:
throw new NotSupportedException($"Expected a property or a field but got a {memberExpression.Member}");
}
default:
throw new NotSupportedException($"Expected a member expression but got a {expression.Body}");
}
}

/// <summary>
/// Searches for a property with a public setter that matches the provided <paramref name="propertyName"/> and registers it as a target for member injection.
/// </summary>
/// <param name="propertyName">The name of the to be registered public property</param>
/// <returns></returns>
public StronglyTypedLateInjectorConfigurator<TInstance> UseProperty(string propertyName)
{
PropertyInfo method = (from m in typeof(TInstance).GetRuntimeProperties()
where m.SetMethod?.IsPublic == true
where m.Name == propertyName
PropertyInfo propertyInfo = (from m in typeof(TInstance).GetRuntimeProperties()
where m.SetMethod?.IsPublic == true
where m.Name == propertyName
select m).Single();
return UseProperty(propertyInfo);
}

/// <summary>
/// Searches for a public field that matches the provided <paramref name="fieldName"/> and registers it as a target for member injection.
/// </summary>
/// <param name="fieldName"></param>
/// <returns></returns>
public StronglyTypedLateInjectorConfigurator<TInstance> UseField(string fieldName)
{
FieldInfo fieldInfo = (from m in typeof(TInstance).GetRuntimeFields()
where m.IsPublic
where m.Name == fieldName
select m).Single();
return UseProperty(method);
return UseField(fieldInfo);
}

/// <summary>
/// Registers the provided <paramref name="fieldInfo"/> as a target for member injection.
/// </summary>
/// <param name="fieldInfo"></param>
/// <returns></returns>
public StronglyTypedLateInjectorConfigurator<TInstance> UseField(FieldInfo fieldInfo)
{
_injectionMembers.Add(fieldInfo);
return this;
}

/// <summary>
/// Registers the provided <paramref name="propertyInfo"/> as a target for property injection.
/// Registers the provided <paramref name="propertyInfo"/> as a target for member injection.
/// </summary>
/// <param name="propertyInfo"></param>
/// <returns></returns>
public StronglyTypedLateInjectorConfigurator<TInstance> UseProperty(PropertyInfo propertyInfo)
{
_injectionProperties.Add(propertyInfo);
_injectionMembers.Add(propertyInfo);
return this;
}

internal LateInjectorBinding ToBinding()
{
return new LateInjectorBinding(typeof(TInstance), _bindingMetadata, _injectionMethods, _injectionProperties);
return new LateInjectorBinding(typeof(TInstance), _bindingMetadata, _injectionMethods, _injectionMembers);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public sealed class WeaklyTypedLateInjectorConfigurator
private readonly BindingMetadata _bindingMetadata;
private readonly Type _instanceType;
private readonly ArrayList<MethodInfo> _injectionMethods = new ArrayList<MethodInfo>();
private readonly ArrayList<PropertyInfo> _injectionProperties = new ArrayList<PropertyInfo>();
private readonly ArrayList<MemberInfo> _injectionProperties = new ArrayList<MemberInfo>();

internal WeaklyTypedLateInjectorConfigurator(Type instanceType, BindingMetadata bindingMetadata)
{
Expand All @@ -30,9 +30,9 @@ internal WeaklyTypedLateInjectorConfigurator(Type instanceType, BindingMetadata
public WeaklyTypedLateInjectorConfigurator UseMethod(string methodName)
{
MethodInfo method = (from m in _instanceType.GetRuntimeMethods()
where m.IsPublic
where m.Name == methodName
select m).Single();
where m.IsPublic
where m.Name == methodName
select m).Single();
return UseMethod(method);
}

Expand All @@ -55,9 +55,9 @@ public WeaklyTypedLateInjectorConfigurator UseMethod(MethodInfo methodInfo)
public WeaklyTypedLateInjectorConfigurator UseProperty(string propertyName)
{
PropertyInfo method = (from m in _instanceType.GetRuntimeProperties()
where m.SetMethod?.IsPublic == true
where m.Name == propertyName
select m).Single();
where m.SetMethod?.IsPublic == true
where m.Name == propertyName
select m).Single();
return UseProperty(method);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Singularity/Singularity.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net452;netstandard2.0</TargetFrameworks>
<TargetFramework>netstandard2.0</TargetFramework>
<Authors>Barsonax</Authors>
<Description>The core library for the singularity ioc container</Description>
<PackageProjectUrl>https://github.com/Barsonax/Singularity</PackageProjectUrl>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net472;netcoreapp2.0</TargetFrameworks>
<TargetFramework>netcoreapp2.0</TargetFramework>
<Configurations>Debug;Release;z_CI_config</Configurations>
</PropertyGroup>

Expand Down
40 changes: 39 additions & 1 deletion src/Tests/Singularity.Test/Injection/LateInjectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void MethodInject_InjectsCorrectDependencies()
}

[Fact]
public void PropertyInject_InjectsCorrectDependencies()
public void PropertyInject_Name_InjectsCorrectDependencies()
{
//ARRANGE
var container = new Container(builder =>
Expand All @@ -44,6 +44,44 @@ public void PropertyInject_InjectsCorrectDependencies()
Assert.IsType<TestService10>(instance.TestService10);
}

[Fact]
public void PropertyInject_Expression_InjectsCorrectDependencies()
{
//ARRANGE
var container = new Container(builder =>
{
builder.Register<ITestService10, TestService10>();
builder.LateInject<MethodInjectionClass>(c => c
.UseMember(o => o.TestService10));
});
var instance = new MethodInjectionClass();

//ACT
container.LateInject(instance);

//ASSERT
Assert.IsType<TestService10>(instance.TestService10);
}

[Fact]
public void FieldInject_Expression_InjectsCorrectDependencies()
{
//ARRANGE
var container = new Container(builder =>
{
builder.Register<ITestService10, TestService10>();
builder.LateInject<MethodInjectionClass>(c => c
.UseMember(o => o.TestService10Field));
});
var instance = new MethodInjectionClass();

//ACT
container.LateInject(instance);

//ASSERT
Assert.IsType<TestService10>(instance.TestService10Field);
}

[Fact]
public void MethodInject_Scoped_InjectsCorrectDependencies()
{
Expand Down
2 changes: 1 addition & 1 deletion src/Tests/Singularity.Test/Singularity.Test.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net472;netcoreapp2.0</TargetFrameworks>
<TargetFramework>netcoreapp2.0</TargetFramework>
<Configurations>Debug;Release;z_CI_config</Configurations>
<NoWarn>1701;1702;1705;1591;NU1701;NU1702;CS1591;CS1574;CS1711</NoWarn>
<LangVersion>8.0</LangVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace Singularity.TestClasses.TestClasses
{
public class MethodInjectionClass
{
public ITestService10 TestService10Field;
public ITestService10? TestService10 { get; set; }

public ITestService10? TestService10noSetter { get; }
Expand Down

0 comments on commit 10fa667

Please sign in to comment.