Skip to content

Commit

Permalink
StubManager can instantiate generic classes now
Browse files Browse the repository at this point in the history
  • Loading branch information
MCKanpolat committed Mar 2, 2018
1 parent 947d679 commit 10b5a01
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 15 deletions.
9 changes: 9 additions & 0 deletions src/StubGenerator.Test.Models/GenericModel`1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace StubGenerator.Test.Models
{
public class GenericModel<T> where T : class
{
public int Status { get; set; }

public T Data { get; set; }
}
}
12 changes: 12 additions & 0 deletions src/StubGenerator.Test.Models/GenericModel`2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace StubGenerator.Test.Models
{
public class GenericModel<T1, T2>
where T1 : class
where T2 : class
{
public int Status { get; set; }

public T1 GenericOne { get; set; }
public T2 GenericTwo { get; set; }
}
}
38 changes: 34 additions & 4 deletions src/StubGenerator.Test/StubManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public StubManagerTests()
_stubManager = new StubManager(stubManagerOptions);
}

[Fact(DisplayName = "Mapping_Check_By_Naming_Default_Conventions")]
[Fact(DisplayName = "Mapping Check By Naming Default Conventions")]
public void Naming_Mapping_Check()
{
var stubDto = _stubManager.CreateNew<PersonDto>();
Expand All @@ -26,7 +26,7 @@ public void Naming_Mapping_Check()
}


[Fact(DisplayName = "Mapping_Check_By_Naming_Default_Conventions_List_Of")]
[Fact(DisplayName = "Mapping Check By Naming Default Conventions List Of")]
public void Naming_Mapping_Check_List_Of()
{
var listOfDto = _stubManager.CreateListOfSize<PersonDto>(10);
Expand All @@ -37,7 +37,7 @@ public void Naming_Mapping_Check_List_Of()
Assert.Equal(10, listOfDto.Count);
}

[Fact(DisplayName = "Mapping_Check_By_Naming_Default_Conventions_Big_List")]
[Fact(DisplayName = "Mapping Check By Naming Default Conventions Big List")]
public void Naming_Mapping_Check_Big_List()
{
var listOfDto = _stubManager.CreateListOfSize<PersonDto>(100);
Expand All @@ -49,7 +49,7 @@ public void Naming_Mapping_Check_Big_List()
}


[Fact(DisplayName = "Mapping_Check_By_Naming_Default_Conventions_DE_Culture")]
[Fact(DisplayName = "Mapping Check By Naming Default Conventions DE Culture")]
public void Naming_Mapping_Check_Culture()
{
var deCulture = new CultureInfo("de-DE");
Expand Down Expand Up @@ -164,5 +164,35 @@ public void Check_Unsupported_Types()
Assert.NotNull(generatedStubData);
Assert.Null(generatedStubData.ByteArray);
}


[Fact(DisplayName = "Should Generate Generic Class")]
public void Should_Generate_Generic_Class()
{
var generatedStubData = _stubManager.InvokeCreateNew("StubGenerator.Test.Models.GenericModel<StubGenerator.Test.Models.ModelWithComplexTypeProperty, StubGenerator.Test.Models>, StubGenerator.Test.Models");
Assert.NotNull(generatedStubData);
}

[Fact(DisplayName = "Should Generate Generic Class With Argument Count Specified")]
public void Should_Generate_Generic_Class_With_Argument_Count_Specified()
{
var generatedStubData = _stubManager.InvokeCreateNew("StubGenerator.Test.Models.GenericModel`1<StubGenerator.Test.Models.ModelWithComplexTypeProperty, StubGenerator.Test.Models>, StubGenerator.Test.Models");
Assert.NotNull(generatedStubData);
}


[Fact(DisplayName = "Should Generate Generic Class With 2 Argument")]
public void Should_Generate_Generic_Class_With_2_Argument()
{
var generatedStubData = _stubManager.InvokeCreateNew("StubGenerator.Test.Models.GenericModel<StubGenerator.Test.Models.ModelWithComplexTypeProperty, StubGenerator.Test.Models;StubGenerator.Test.Models.ComplexModel, StubGenerator.Test.Models>, StubGenerator.Test.Models");
Assert.NotNull(generatedStubData);
}

[Fact(DisplayName = "Should Generate Generic Class With 2 Argument Count Specified")]
public void Should_Generate_Generic_Class_With_2_Argument_Count_Specified()
{
var generatedStubData = _stubManager.InvokeCreateNew("StubGenerator.Test.Models.GenericModel`2<StubGenerator.Test.Models.ModelWithComplexTypeProperty, StubGenerator.Test.Models;StubGenerator.Test.Models.ComplexModel, StubGenerator.Test.Models>, StubGenerator.Test.Models");
Assert.NotNull(generatedStubData);
}
}
}
13 changes: 13 additions & 0 deletions src/StubMiddleware.Core/Core/Conventions/CountryConventionMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Reflection;
using StubGenerator.Core.FakeDataGenerators;

namespace StubGenerator.Core.Conventions
{
public class CountryConventionMap : IConventionMap
{
public Predicate<PropertyInfo> Condition => w => w.PropertyType == typeof(string) && w.Name.ToLowerInvariant().Contains("country");

public IValueGenerator Generator => new CountryValueGenerator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ namespace StubGenerator.Defaults
{
public class LastnameConvetionMap : IConventionMap
{
public Predicate<PropertyInfo> Condition => w => w.PropertyType == typeof(string) && w.Name.ToLowerInvariant().Contains("name") && w.Name.ToLowerInvariant().Contains("last");
public Predicate<PropertyInfo> Condition => w => w.PropertyType == typeof(string) &&
((w.Name.ToLowerInvariant().Contains("name") && w.Name.ToLowerInvariant().Contains("last")) || w.Name.ToLower().Contains("surname"));

public IValueGenerator Generator => new LastNameValueGenerator();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Reflection;
using StubGenerator.Core.FakeDataGenerators;

namespace StubGenerator.Core.Conventions
{
public class StreetNameConventionMap : IConventionMap
{
public Predicate<PropertyInfo> Condition => w => w.PropertyType == typeof(string) && w.Name.ToLowerInvariant().Contains("street");

public IValueGenerator Generator => new StreetNameValueGenerator();
}
}
13 changes: 13 additions & 0 deletions src/StubMiddleware.Core/Core/Conventions/ZipCodeConventionMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Reflection;
using StubGenerator.Core.FakeDataGenerators;

namespace StubGenerator.Core.Conventions
{
public class ZipCodeConventionMap : IConventionMap
{
public Predicate<PropertyInfo> Condition => w => w.PropertyType == typeof(string) && (w.Name.ToLowerInvariant().Contains("zipcode"));

public IValueGenerator Generator => new ZipCodeValueGenerator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@ namespace StubGenerator.Defaults
public class DefaultConventionMappingProfile : IConventionMappingProfile
{
private readonly List<IConventionMap> _conventions;
public DefaultConventionMappingProfile()
{
_conventions = new List<IConventionMap>();
_conventions.Add(new FirstnameConventionMap());
_conventions.Add(new LastnameConvetionMap());
_conventions.Add(new EmailConventionMap());
_conventions.Add(new PhoneNumberConventionMap());
_conventions.Add(new CompanyNameConventionMap());
}
public DefaultConventionMappingProfile() => _conventions = new List<IConventionMap>
{
new FirstnameConventionMap(),
new LastnameConvetionMap(),
new EmailConventionMap(),
new PhoneNumberConventionMap(),
new CompanyNameConventionMap(),
new UserNameConventionMap(),
new StreetNameConventionMap(),
new CountryConventionMap(),
new ZipCodeConventionMap()
};

public IEnumerable<IConventionMap> Conventions => _conventions;
}
Expand Down
49 changes: 48 additions & 1 deletion src/StubMiddleware.Core/Extensions/StubManagerExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;

namespace StubGenerator.Core
{
public static class StubManagerExtensions
{
private static readonly Regex genericTypeRegex = new Regex("<(.+?)>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static Type LoadType(string typeName)
{
if (string.IsNullOrWhiteSpace(typeName))
{
throw new ArgumentException("message", nameof(typeName));
}
var result = Type.GetType(typeName);
Type result = null;
var match = genericTypeRegex.Match(typeName);
if (match.Success)
{
var matchValue = match.Value;
var outerClassName = typeName.Replace(matchValue, "");
var innerClassNames = matchValue.Trim('<', '>').Split(';');
var genericArgumentTypes = new HashSet<Type>();

foreach (var innerClassName in innerClassNames)
{
var innerType = Type.GetType(innerClassName, false);
if (innerType == null)
throw new TypeLoadException($"The type '{innerClassName}' couldn't be loaded");

genericArgumentTypes.Add(innerType);
}

if (!outerClassName.Contains("`"))
{
//If generic argument count doesn't specified
//Rewrite generic class name with generic argument count
var splittedClassName = outerClassName.Split(',');
if (splittedClassName.Count()!=2)
throw new TypeLoadException($"The type '{outerClassName}' couldn't be loaded");
outerClassName = $"{splittedClassName[0]}`{genericArgumentTypes.Count}, {splittedClassName[1]}";
}

var outerType = Type.GetType(outerClassName, false);
if (outerType == null)
throw new TypeLoadException($"The type '{outerClassName}' couldn't be loaded");

if (!outerType.IsGenericType)
throw new TypeAccessException($"The type '{outerClassName}' must be a generic class");

if (outerType.GetGenericArguments().Count() != genericArgumentTypes.Count)
throw new TypeAccessException($"The type '{outerClassName}' generic arguments mismatch");

result = outerType.MakeGenericType(genericArgumentTypes.ToArray());
}
else
{
result = Type.GetType(typeName, false);
}

if (result == null)
throw new TypeLoadException($"The type '{typeName}' couldn't be loaded");
return result;
Expand Down

0 comments on commit 10b5a01

Please sign in to comment.