Makes sure supplied arguments cannot be used more than once. (#7814)

This commit is contained in:
Sebastiaan Janssen
2020-05-26 09:19:27 +02:00
committed by GitHub
2 changed files with 45 additions and 3 deletions
+17 -3
View File
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Umbraco.Core.Composing;
@@ -77,15 +78,28 @@ namespace Umbraco.Core
var ctorParameters = ctor.GetParameters();
var ctorArgs = new object[ctorParameters.Length];
var availableArgs = new List<object>(args);
var i = 0;
foreach (var parameter in ctorParameters)
{
// no! IsInstanceOfType is not ok here
// ReSharper disable once UseMethodIsInstanceOfType
var arg = args?.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType()));
ctorArgs[i++] = arg ?? factory.GetInstance(parameter.ParameterType);
var idx = availableArgs.FindIndex(a => parameter.ParameterType.IsAssignableFrom(a.GetType()));
if(idx >= 0)
{
// Found a suitable supplied argument
ctorArgs[i++] = availableArgs[idx];
// A supplied argument can be used at most once
availableArgs.RemoveAt(idx);
}
else
{
// None of the provided arguments is suitable: get an instance from the factory
ctorArgs[i++] = factory.GetInstance(parameter.ParameterType);
}
}
return ctor.Invoke(ctorArgs);
}
}
}
}
@@ -332,6 +332,22 @@ namespace Umbraco.Tests.Composing
Assert.AreSame(s1, s2);
}
[Test]
public void CanRegisterMultipleSameTypeParametersWithCreateInstance()
{
var register = GetRegister();
var factory = register.CreateFactory();
register.Register<Thing4>(factory =>
{
var param1 = "param1";
var param2 = "param2";
return factory.CreateInstance<Thing4>(param1, param2);
});
var instance = factory.GetInstance<Thing4>();
Assert.AreNotEqual(instance.Thing, instance.AnotherThing);
}
public interface IThing { }
public abstract class ThingBase : IThing { }
@@ -352,5 +368,17 @@ namespace Umbraco.Tests.Composing
public IEnumerable<ThingBase> Things { get; }
}
public class Thing4 : ThingBase
{
public readonly string Thing;
public readonly string AnotherThing;
public Thing4(string thing, string anotherThing)
{
Thing = thing;
AnotherThing = anotherThing;
}
}
}
}