Skip to content

Commit

Permalink
Add support for nested model types and add support for non-generic ne…
Browse files Browse the repository at this point in the history
…sted template base classes.

fixes #240
  • Loading branch information
matthid committed Feb 23, 2015
1 parent 2f08026 commit 102ebae
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 18 deletions.
4 changes: 2 additions & 2 deletions buildConfig.fsx
Expand Up @@ -44,8 +44,8 @@ printfn "BUILDING VERSION: %s" version_nuget
// !!!!!!!!!!!!!!!!!!!
// UPDATE RELEASE NOTES AS WELL!
// !!!!!!!!!!!!!!!!!!!
let version_razor4 = "4.1.0.0"
let version_razor4_nuget = "4.1.0-beta1"
let version_razor4 = "4.1.1.0"
let version_razor4_nuget = "4.1.1-beta1"
let version_roslyn_nuget = "3.5.1-beta1"
let version_roslyn_razor4_nuget = "4.0.1-beta1"
let commitHash = Information.getCurrentSHA1(".")
Expand Down
6 changes: 5 additions & 1 deletion doc/ReleaseNotes.md
@@ -1,4 +1,8 @@
### 3.6.0 / 4.1.0-beta1
### 3.6.1 / 4.1.1-beta1
* Add support for nested model types as well
* Fix a bug with non-generic nested template base classes.

### 3.6.0 / 4.1.0-beta1
* ICodeInspector API is now obsolete (it has been removed in 4.0.0).
* Nested classes can now be used as template-base-class.
* ViewBag data can now be used in overwritten SetModel calls
Expand Down
23 changes: 10 additions & 13 deletions src/source/RazorEngine.Core/Compilation/CompilerServicesUtility.cs
Expand Up @@ -127,12 +127,11 @@ public static string ResolveCSharpTypeName(Type type)
if (IsDynamicType(type))
return "dynamic";

var rawFullName = CSharpGetRawTypeName(type);
if (!type.IsGenericType)
return type.FullName;
return rawFullName;

return type.Namespace
+ "."
+ type.Name.Substring(0, type.Name.IndexOf('`'))
return rawFullName
+ "<"
+ string.Join(", ", type.GetGenericArguments().Select(ResolveCSharpTypeName))
+ ">";
Expand All @@ -151,12 +150,11 @@ public static string ResolveVBTypeName(Type type)
if (IsDynamicType(type))
return "Object";

var rawFullName = VBGetRawTypeName(type);
if (!type.IsGenericType)
return type.FullName;
return rawFullName;

return type.Namespace
+ "."
+ type.Name.Substring(0, type.Name.IndexOf('`'))
return rawFullName
+ "(Of"
+ string.Join(", ", type.GetGenericArguments().Select(ResolveVBTypeName))
+ ")";
Expand Down Expand Up @@ -211,12 +209,11 @@ public static string CSharpGetRawTypeName(Type type)
if (type == null)
throw new ArgumentNullException("templateType");

if (!type.IsGenericTypeDefinition || !type.IsGenericType)
return type.FullName;
string fullName = type.FullName;
if (type.IsGenericTypeDefinition || type.IsGenericType)
fullName = type.FullName.Substring(0, type.FullName.IndexOf('`'));

var templateTypeName =
type.FullName.Substring(0, type.FullName.IndexOf('`')).Replace("+", ".");
return templateTypeName;
return fullName.Replace("+", ".");;
}


Expand Down
Expand Up @@ -19,20 +19,86 @@ public class CompilerServicesUtilityTestFixture
/// Check that we can generate the raw type name from a nested generic class.
/// </summary>
[Test]
public void CompilerServiceUtility_CheckNestedClass()
public void CompilerServiceUtility_CheckNestedBaseClass()
{
var result = CompilerServicesUtility.CSharpGetRawTypeName(typeof(HostingClass.NestedBaseClass<>));
Assert.AreEqual("Test.RazorEngine.TestTypes.BaseTypes.HostingClass.NestedBaseClass", result);
}

/// <summary>
/// Check that we can generate the raw type name from a nested generic class.
/// </summary>
[Test]
public void CompilerServiceUtility_CheckNestedNonGenericBaseClass()
{
var result = CompilerServicesUtility.CSharpGetRawTypeName(typeof(HostingClass.NonGenericNestedBaseClass));
Assert.AreEqual("Test.RazorEngine.TestTypes.BaseTypes.HostingClass.NonGenericNestedBaseClass", result);
}

/// <summary>
/// Check that we can generate the raw type name from a normal generic class
/// </summary>
[Test]
public void CompilerServiceUtility_CheckNormalGenericClass()
public void CompilerServiceUtility_CheckNormalGenericBaseClass()
{
var result = CompilerServicesUtility.CSharpGetRawTypeName(typeof(AddLanguageInfo_Viewbag<>));
Assert.AreEqual("Test.RazorEngine.TestTypes.BaseTypes.AddLanguageInfo_Viewbag", result);
}

private IEnumerable<string> IteratorHelper()
{
yield return "first";
yield return "second";
}
/// <summary>
/// Check that we can generate the type name from a iterator type
/// </summary>
[Test]
public void CompilerServiceUtility_CheckCSharpIteratorType()
{
var type = IteratorHelper().GetType();
var result = CompilerServicesUtility.ResolveCSharpTypeName(type);
Assert.AreEqual("System.Collections.Generic.IEnumerable<System.String>", result);
}

/// <summary>
/// Check that we can generate the type name from a dynamic type
/// </summary>
[Test]
public void CompilerServiceUtility_CheckDynamicType()
{
var result = CompilerServicesUtility.ResolveCSharpTypeName(typeof(System.Dynamic.DynamicObject));
Assert.AreEqual("dynamic", result);
}

/// <summary>
/// Check that we can generate the type name from a normal class
/// </summary>
[Test]
public void CompilerServiceUtility_CheckNonGenericType()
{
var result = CompilerServicesUtility.ResolveCSharpTypeName(typeof(System.String));
Assert.AreEqual("System.String", result);
}

/// <summary>
/// Check that we can generate the type name from a normal nested class
/// </summary>
[Test]
public void CompilerServiceUtility_CheckNonGenericNestedType()
{
var result = CompilerServicesUtility.ResolveCSharpTypeName(typeof(HostingClass.NestedClass));
Assert.AreEqual("Test.RazorEngine.TestTypes.BaseTypes.HostingClass.NestedClass", result);
}

/// <summary>
/// Check that we can generate the type name from a generic nested class
/// </summary>
[Test]
public void CompilerServiceUtility_CheckGenericNestedType()
{
var result = CompilerServicesUtility.ResolveCSharpTypeName(typeof(HostingClass.GenericNestedClass<string>));
Assert.AreEqual("Test.RazorEngine.TestTypes.BaseTypes.HostingClass.GenericNestedClass<System.String>", result);
}
}
}
31 changes: 31 additions & 0 deletions src/test/Test.RazorEngine.Core/RazorEngineServiceTestFixture.cs
Expand Up @@ -426,5 +426,36 @@ public void RazorEngineService_TestNestedBaseClass()
config.BaseTemplateType = typeof(HostingClass.NestedBaseClass<>);
});
}

/// <summary>
/// Tests that nested base classes work.
/// </summary>
[Test]
public void RazorEngineService_TestNestedModelClass()
{
RunTestHelper(service =>
{
var template = @"@Model.TestProperty";
string result = service.RunCompile(template, "key", typeof(HostingClass.NestedClass),
new HostingClass.NestedClass() { TestProperty = "test" });
Assert.AreEqual("test", result);
});
}

/// <summary>
/// Tests that nested base classes work.
/// </summary>
[Test]
public void RazorEngineService_TestNestedGenericModelClass()
{
RunTestHelper(service =>
{
var template = @"@Model.TestProperty";
string result = service.RunCompile(template, "key", typeof(HostingClass.GenericNestedClass<string>),
new HostingClass.GenericNestedClass<string>() { TestProperty = "test" });
Assert.AreEqual("test", result);
});
}

}
}
Expand Up @@ -13,5 +13,20 @@ public class NestedBaseClass<T> : TemplateBase<T>
{
public string TestProperty { get { return "mytest"; } }
}

public class NonGenericNestedBaseClass : TemplateBase
{
public string TestProperty { get { return "mytest"; } }
}

public class NestedClass
{
public string TestProperty { get; set; }
}

public class GenericNestedClass<T>
{
public T TestProperty { get; set; }
}
}
}

0 comments on commit 102ebae

Please sign in to comment.