Skip to content

Commit

Permalink
Moved DefaultExecuteStrategy.DetermineTypeToBuild to IBuildConfigurat…
Browse files Browse the repository at this point in the history
…ion.GetBuildType
  • Loading branch information
roryprimrose committed Feb 2, 2020
1 parent 0824110 commit e98d13c
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 38 deletions.
118 changes: 117 additions & 1 deletion ModelBuilder.UnitTests/BuildConfigurationExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ public void AddExecuteOrderRuleWithRegexThrowsExceptionWithNullExpressionTest()

var target = new BuildConfiguration();

Action action = () => target.AddExecuteOrderRule((Regex)null, priority);
Action action = () => target.AddExecuteOrderRule((Regex) null, priority);

action.Should().Throw<ArgumentNullException>();
}
Expand Down Expand Up @@ -771,6 +771,122 @@ public void CreateTThrowsExceptionWithNullBuildConfigurationTest()
action.Should().Throw<ArgumentNullException>();
}

[Fact]
public void GetBuildTypeReturnsSourceWhenNoTypeMappingIsFound()
{
var source = typeof(string);

var buildLog = Substitute.For<IBuildLog>();
var sut = new BuildConfiguration().Mapping<Stream, MemoryStream>();

var actual = sut.GetBuildType(source, buildLog);

actual.Should().Be<string>();
}

[Fact]
public void GetBuildTypeReturnsSourceWhenTypeMappingIsEmpty()
{
var source = typeof(string);

var buildLog = Substitute.For<IBuildLog>();
var sut = new BuildConfiguration();

var actual = sut.GetBuildType(source, buildLog);

actual.Should().Be<string>();
}

[Fact]
public void GetBuildTypeReturnsSourceWhenTypeMappingIsNull()
{
var source = typeof(string);

var buildLog = Substitute.For<IBuildLog>();
var sut = Substitute.For<IBuildConfiguration>();

var actual = sut.GetBuildType(source, buildLog);

actual.Should().Be<string>();
}

[Fact]
public void GetBuildTypeReturnsTargetTypeWhenSourceIsAbstractClass()
{
var source = typeof(Entity);

var buildLog = Substitute.For<IBuildLog>();
var sut = new BuildConfiguration();

var actual = sut.GetBuildType(source, buildLog);

actual.Should().Be<Person>();
}

[Fact]
public void GetBuildTypeReturnsTargetTypeWhenSourceIsInterface()
{
var source = typeof(ITestItem);

var buildLog = Substitute.For<IBuildLog>();
var sut = new BuildConfiguration();

var actual = sut.GetBuildType(source, buildLog);

actual.Should().Be<TestItem>();
}

[Fact]
public void GetBuildTypeReturnsTargetTypeWhenTypeMappingFound()
{
var source = typeof(Stream);

var buildLog = Substitute.For<IBuildLog>();
var sut = new BuildConfiguration().Mapping<Stream, MemoryStream>();

var actual = sut.GetBuildType(source, buildLog);

actual.Should().Be<MemoryStream>();
}

[Fact]
public void GetBuildTypeThrowsExceptionWithNullBuildLog()
{
var source = typeof(string);

var sut = Substitute.For<IBuildConfiguration>();

Action action = () => sut.GetBuildType(source, null);

action.Should().Throw<ArgumentNullException>();
}

[Fact]
public void GetBuildTypeThrowsExceptionWithNullConfiguration()
{
var source = typeof(string);

var buildLog = Substitute.For<IBuildLog>();

IBuildConfiguration config = null;

Action action = () => config.GetBuildType(source, buildLog);

action.Should().Throw<ArgumentNullException>();
}

[Fact]
public void GetBuildTypeThrowsExceptionWithNullSourceType()
{
var buildLog = Substitute.For<IBuildLog>();

var sut = Substitute.For<IBuildConfiguration>();

Action action = () => sut.GetBuildType(null, buildLog);

action.Should().Throw<ArgumentNullException>();
}

[Fact]
public void IgnoringReturnsNewBuildConfigurationWithIgnoreRuleAppendedTest()
{
Expand Down
58 changes: 58 additions & 0 deletions ModelBuilder/BuildConfigurationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,64 @@ public static T Create<T>(this IBuildConfiguration buildConfiguration, params ob
return buildConfiguration.UsingExecuteStrategy<DefaultExecuteStrategy>().Create(instanceType, args);
}

/// <summary>
/// Gets the type to build which may be different to the provided type.
/// </summary>
/// <param name="configuration">The build configuration.</param>
/// <param name="source">The source type.</param>
/// <param name="buildLog">The build log.</param>
/// <returns>The type of object to build.</returns>
public static Type GetBuildType(this IBuildConfiguration configuration, Type source, IBuildLog buildLog)
{
if (configuration == null)
{
throw new ArgumentNullException(nameof(configuration));
}

if (source == null)
{
throw new ArgumentNullException(nameof(source));
}

if (buildLog == null)
{
throw new ArgumentNullException(nameof(buildLog));
}

var typeMappingRule = configuration.TypeMappingRules?.Where(x => x.SourceType == source).FirstOrDefault();

if (typeMappingRule != null)
{
buildLog.MappedType(source, typeMappingRule.TargetType);

return typeMappingRule.TargetType;
}

// There is no type mapping for this type
if (source.IsInterface
|| source.IsAbstract)
{
// Automatically resolve a derived type within the same assembly
var assemblyTypes = source.GetTypeInfo().Assembly.GetTypes();
var possibleTypes = from x in assemblyTypes
where x.IsPublic && x.IsInterface == false && x.IsAbstract == false && source.IsAssignableFrom(x)
select x;

var matchingType = possibleTypes.FirstOrDefault(source.IsAssignableFrom);

if (matchingType == null)
{
return source;
}

buildLog.MappedType(source, matchingType);

return matchingType;
}

return source;
}

/// <summary>
/// Appends a new <see cref="IIgnoreRule" /> to the build configuration using the specified expression.
/// </summary>
Expand Down
38 changes: 1 addition & 37 deletions ModelBuilder/DefaultExecuteStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ protected virtual object Build(Type type, string referenceName, object context,

EnsureInitialized();

var typeToBuild = DetermineTypeToBuild(type);
var typeToBuild = Configuration.GetBuildType(type, Log);

if (typeToBuild == null)
{
Expand Down Expand Up @@ -502,42 +502,6 @@ private Exception CreateBuildException(Type type, string referenceName, object c
return new Tuple<object, object[]>(instance, args);
}

private Type DetermineTypeToBuild(Type type)
{
var typeMappingRule = Configuration.TypeMappingRules?.Where(x => x.SourceType == type).FirstOrDefault();

if (typeMappingRule != null)
{
Log.MappedType(type, typeMappingRule.TargetType);

return typeMappingRule.TargetType;
}

// There is no type mapping for this type
if (type.IsInterface
|| type.IsAbstract)
{
// Automatically resolve a derived type within the same assembly
var assemblyTypes = type.GetTypeInfo().Assembly.GetTypes();
var possibleTypes = from x in assemblyTypes
where x.IsPublic && x.IsInterface == false && x.IsAbstract == false && type.IsAssignableFrom(x)
select x;

var matchingType = possibleTypes.FirstOrDefault(type.IsAssignableFrom);

if (matchingType == null)
{
return type;
}

Log.MappedType(type, matchingType);

return matchingType;
}

return type;
}

private void EnsureInitialized()
{
if (Configuration == null)
Expand Down

0 comments on commit e98d13c

Please sign in to comment.