Skip to content

Commit

Permalink
Add ReflexConstructorAttribute
Browse files Browse the repository at this point in the history
  • Loading branch information
gustavopsantos committed Jun 4, 2024
1 parent 6408738 commit da4dec5
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 1 deletion.
69 changes: 69 additions & 0 deletions Assets/Reflex.EditModeTests/ReflexConstructorAttributeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using FluentAssertions;
using NUnit.Framework;
using Reflex.Attributes;
using Reflex.Core;

namespace Reflex.EditModeTests
{
public class ReflexConstructorAttributeTests
{
private class ClassWithReflexConstructorIdentifiedByMaxAmountOfArguments
{
public bool ConstructedWithEmptyConstructor { get; }
public bool ConstructedWithNonEmptyConstructor { get; }

public ClassWithReflexConstructorIdentifiedByMaxAmountOfArguments()
{
ConstructedWithEmptyConstructor = true;
}

public ClassWithReflexConstructorIdentifiedByMaxAmountOfArguments(object a, int b)
{
ConstructedWithNonEmptyConstructor = true;
}
}

private class ClassWithReflexConstructorIdentifiedByReflexConstructorAttribute
{
public bool ConstructedWithEmptyConstructor { get; }
public bool ConstructedWithNonEmptyConstructor { get; }

[ReflexConstructor]
public ClassWithReflexConstructorIdentifiedByReflexConstructorAttribute()
{
ConstructedWithEmptyConstructor = true;
}

public ClassWithReflexConstructorIdentifiedByReflexConstructorAttribute(object a, int b)
{
ConstructedWithNonEmptyConstructor = true;
}
}

[Test]
public void ClassWithMultipleConstructors_WithoutAnyReflexConstructorAttribute_ShouldBeConstructedUsing_ConstructorWithMostArguments()
{
var container = new ContainerBuilder()
.AddSingleton(new object())
.AddSingleton(42)
.Build();

var result = container.Construct<ClassWithReflexConstructorIdentifiedByMaxAmountOfArguments>();
result.ConstructedWithEmptyConstructor.Should().BeFalse();
result.ConstructedWithNonEmptyConstructor.Should().BeTrue();
}

[Test]
public void ClassWithMultipleConstructors_WithOneDefiningReflexConstructorAttribute_ShouldBeConstructedUsing_ConstructorWithReflexConstructorAttribute()
{
var container = new ContainerBuilder()
.AddSingleton(new object())
.AddSingleton(42)
.Build();

var result = container.Construct<ClassWithReflexConstructorIdentifiedByReflexConstructorAttribute>();
result.ConstructedWithEmptyConstructor.Should().BeTrue();
result.ConstructedWithNonEmptyConstructor.Should().BeFalse();
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions Assets/Reflex/Attributes/ReflexConstructorAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using JetBrains.Annotations;

namespace Reflex.Attributes
{
[MeansImplicitUse(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
[AttributeUsage(AttributeTargets.Constructor)]
public class ReflexConstructorAttribute : Attribute
{
}
}
11 changes: 11 additions & 0 deletions Assets/Reflex/Attributes/ReflexConstructorAttribute.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion Assets/Reflex/Caching/TypeConstructionInfoCache.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Reflex.Attributes;
using Reflex.Extensions;
using Reflex.Reflectors;

Expand All @@ -25,7 +26,13 @@ private static TypeConstructionInfo Generate(Type type)
{
if (type.TryGetConstructors(out var constructors))
{
var constructor = constructors.MaxBy(ctor => ctor.GetParameters().Length);
var constructor = constructors.FirstOrDefault(c => Attribute.IsDefined(c, typeof(ReflexConstructorAttribute))); // Try to get a constructor that defines ReflexConstructor

if (constructor == null)
{
constructor = constructors.MaxBy(ctor => ctor.GetParameters().Length); // Gets the constructor with most arguments
}

var parameters = constructor.GetParameters().Select(p => p.ParameterType).ToArray();
return new TypeConstructionInfo(ActivatorFactoryManager.Factory.GenerateActivator(type, constructor, parameters), parameters);
}
Expand Down

0 comments on commit da4dec5

Please sign in to comment.