* Refactoring RazorFileInfoCollectionGenerator to not be instantiated.
* Adding CompilerGeneratedAttribute to generated code. * Adding unit tests for RazorFileInfoCollectionGenerator.
This commit is contained in:
parent
1723ef0e97
commit
c631d533c4
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Microsoft.AspNet.Mvc.Razor.Precompilation;
|
||||
using Microsoft.Dnx.Runtime;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility type to code generate <see cref="RazorFileInfoCollection"/> types.
|
||||
/// </summary>
|
||||
public static class RazorFileInfoCollectionGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates CSharp code for the specified <paramref name="fileInfoCollection"/>.
|
||||
/// </summary>
|
||||
/// <param name="fileInfoCollection">The <see cref="RazorFileInfoCollection"/>.</param>
|
||||
/// <returns></returns>
|
||||
public static string GenerateCode([NotNull] RazorFileInfoCollection fileInfoCollection)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
builder.Append(
|
||||
$@"namespace __ASP_ASSEMBLY
|
||||
{{
|
||||
[{typeof(CompilerGeneratedAttribute).FullName}]
|
||||
public class __PreGeneratedViewCollection : {typeof(RazorFileInfoCollection).FullName}
|
||||
{{
|
||||
public __PreGeneratedViewCollection()
|
||||
{{
|
||||
{nameof(RazorFileInfoCollection.AssemblyResourceName)} = @""{fileInfoCollection.AssemblyResourceName}"";
|
||||
{nameof(RazorFileInfoCollection.SymbolsResourceName)} = @""{fileInfoCollection.SymbolsResourceName}"";
|
||||
FileInfos = new System.Collections.Generic.List<{typeof(RazorFileInfo).FullName}>
|
||||
{{");
|
||||
|
||||
foreach (var fileInfo in fileInfoCollection.FileInfos)
|
||||
{
|
||||
builder.Append(
|
||||
$@"
|
||||
new {typeof(RazorFileInfo).FullName}
|
||||
{{
|
||||
{nameof(RazorFileInfo.FullTypeName)} = @""{fileInfo.FullTypeName}"",
|
||||
{nameof(RazorFileInfo.RelativePath)} = @""{fileInfo.RelativePath}""
|
||||
}},");
|
||||
}
|
||||
|
||||
builder.Append(
|
||||
$@"
|
||||
}};
|
||||
}}
|
||||
|
||||
private static {typeof(System.Reflection.Assembly).FullName} _loadedAssembly;
|
||||
|
||||
public override {typeof(System.Reflection.Assembly).FullName} LoadAssembly(
|
||||
{typeof(IAssemblyLoadContext).FullName} loadContext)
|
||||
{{
|
||||
if (_loadedAssembly == null)
|
||||
{{
|
||||
_loadedAssembly = base.LoadAssembly(loadContext);
|
||||
}}
|
||||
return _loadedAssembly;
|
||||
}}
|
||||
}}
|
||||
}}");
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Microsoft.AspNet.Mvc.Razor.Compilation;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.Dnx.Compilation.CSharp;
|
||||
using Microsoft.Dnx.Runtime;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor.Precompilation
|
||||
{
|
||||
public class RazorFileInfoCollectionGenerator
|
||||
{
|
||||
private string _fileFormat;
|
||||
|
||||
public RazorFileInfoCollectionGenerator([NotNull] RazorFileInfoCollection fileInfoCollection,
|
||||
[NotNull] CompilationSettings compilationSettings)
|
||||
{
|
||||
RazorFileInfoCollection = fileInfoCollection;
|
||||
CompilationSettings = compilationSettings;
|
||||
}
|
||||
|
||||
protected RazorFileInfoCollection RazorFileInfoCollection { get; }
|
||||
|
||||
protected CompilationSettings CompilationSettings { get; }
|
||||
|
||||
public virtual SyntaxTree GenerateCollection()
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
builder.AppendFormat(CultureInfo.InvariantCulture,
|
||||
TopFormat,
|
||||
RazorFileInfoCollection.AssemblyResourceName,
|
||||
RazorFileInfoCollection.SymbolsResourceName);
|
||||
|
||||
foreach (var fileInfo in RazorFileInfoCollection.FileInfos)
|
||||
{
|
||||
var perFileEntry = GenerateFile(fileInfo);
|
||||
builder.Append(perFileEntry);
|
||||
}
|
||||
|
||||
builder.Append(Bottom);
|
||||
|
||||
var sourceCode = builder.ToString();
|
||||
var syntaxTree = SyntaxTreeGenerator.Generate(sourceCode,
|
||||
"__AUTO__GeneratedViewsCollection.cs",
|
||||
CompilationSettings);
|
||||
|
||||
return syntaxTree;
|
||||
}
|
||||
|
||||
protected virtual string GenerateFile([NotNull] RazorFileInfo fileInfo)
|
||||
{
|
||||
return string.Format(FileFormat,
|
||||
fileInfo.RelativePath,
|
||||
fileInfo.FullTypeName);
|
||||
}
|
||||
|
||||
protected virtual string TopFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
$@"using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using {typeof(RazorFileInfoCollection).Namespace};
|
||||
|
||||
namespace __ASP_ASSEMBLY
|
||||
{{{{
|
||||
public class __PreGeneratedViewCollection : {nameof(RazorFileInfoCollection)}
|
||||
{{{{
|
||||
public __PreGeneratedViewCollection()
|
||||
{{{{
|
||||
{nameof(RazorFileInfoCollection.AssemblyResourceName)} = ""{{0}}"";
|
||||
{nameof(RazorFileInfoCollection.SymbolsResourceName)} = ""{{1}}"";
|
||||
var fileInfos = new List<{nameof(RazorFileInfo)}>();
|
||||
{nameof(RazorFileInfoCollection.FileInfos)} = fileInfos;
|
||||
{nameof(RazorFileInfo)} info;
|
||||
";
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string Bottom
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
$@"
|
||||
}}
|
||||
private static Assembly _loadedAssembly;
|
||||
|
||||
public override Assembly LoadAssembly({typeof(IAssemblyLoadContext).FullName} loadContext)
|
||||
{{
|
||||
if (_loadedAssembly == null)
|
||||
{{
|
||||
_loadedAssembly = base.LoadAssembly(loadContext);
|
||||
}}
|
||||
return _loadedAssembly;
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
";
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string FileFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_fileFormat == null)
|
||||
{
|
||||
_fileFormat =
|
||||
$@"
|
||||
info = new {nameof(RazorFileInfo)}
|
||||
{{{{
|
||||
{nameof(RazorFileInfo.RelativePath)} = @""{{0}}"",
|
||||
{nameof(RazorFileInfo.FullTypeName)} = @""{{1}}""
|
||||
}}}};
|
||||
fileInfos.Add(info);
|
||||
";
|
||||
}
|
||||
|
||||
return _fileFormat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -64,12 +64,11 @@ namespace Microsoft.AspNet.Mvc.Razor.Precompilation
|
|||
var result = CreateFileInfoCollection();
|
||||
if (result != null)
|
||||
{
|
||||
var collectionGenerator = new RazorFileInfoCollectionGenerator(
|
||||
result,
|
||||
CompilationSettings);
|
||||
|
||||
var tree = collectionGenerator.GenerateCollection();
|
||||
CompileContext.Compilation = CompileContext.Compilation.AddSyntaxTrees(tree);
|
||||
var generatedCode = RazorFileInfoCollectionGenerator.GenerateCode(result);
|
||||
var syntaxTree = CSharpSyntaxTree.ParseText(
|
||||
generatedCode,
|
||||
SyntaxTreeGenerator.GetParseOptions(CompilationSettings));
|
||||
CompileContext.Compilation = CompileContext.Compilation.AddSyntaxTrees(syntaxTree);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,135 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.Razor.Compilation;
|
||||
using Microsoft.AspNet.Mvc.Razor.Precompilation;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor.Internal
|
||||
{
|
||||
public class RazorFileInfoCollectionGeneratorTest
|
||||
{
|
||||
public static TheoryData GenerateCollection_ProducesExpectedCodeData
|
||||
{
|
||||
get
|
||||
{
|
||||
var expected1 =
|
||||
@"namespace __ASP_ASSEMBLY
|
||||
{
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute]
|
||||
public class __PreGeneratedViewCollection : Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfoCollection
|
||||
{
|
||||
public __PreGeneratedViewCollection()
|
||||
{
|
||||
AssemblyResourceName = @""EmptyAssembly"";
|
||||
SymbolsResourceName = @"""";
|
||||
FileInfos = new System.Collections.Generic.List<Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfo>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
private static System.Reflection.Assembly _loadedAssembly;
|
||||
|
||||
public override System.Reflection.Assembly LoadAssembly(
|
||||
Microsoft.Dnx.Runtime.IAssemblyLoadContext loadContext)
|
||||
{
|
||||
if (_loadedAssembly == null)
|
||||
{
|
||||
_loadedAssembly = base.LoadAssembly(loadContext);
|
||||
}
|
||||
return _loadedAssembly;
|
||||
}
|
||||
}
|
||||
}";
|
||||
var expected2 =
|
||||
@"namespace __ASP_ASSEMBLY
|
||||
{
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute]
|
||||
public class __PreGeneratedViewCollection : Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfoCollection
|
||||
{
|
||||
public __PreGeneratedViewCollection()
|
||||
{
|
||||
AssemblyResourceName = @""TestAssembly"";
|
||||
SymbolsResourceName = @""SymbolsResource"";
|
||||
FileInfos = new System.Collections.Generic.List<Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfo>
|
||||
{
|
||||
new Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfo
|
||||
{
|
||||
FullTypeName = @""SomeType.Name"",
|
||||
RelativePath = @""Views/Home/Index.cshtml""
|
||||
},
|
||||
new Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfo
|
||||
{
|
||||
FullTypeName = @""Different.Name"",
|
||||
RelativePath = @""Views/Home/Different.cshtml""
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private static System.Reflection.Assembly _loadedAssembly;
|
||||
|
||||
public override System.Reflection.Assembly LoadAssembly(
|
||||
Microsoft.Dnx.Runtime.IAssemblyLoadContext loadContext)
|
||||
{
|
||||
if (_loadedAssembly == null)
|
||||
{
|
||||
_loadedAssembly = base.LoadAssembly(loadContext);
|
||||
}
|
||||
return _loadedAssembly;
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
return new TheoryData<RazorFileInfoCollection, string>
|
||||
{
|
||||
{ new EmptyCollection(), expected1 },
|
||||
{ new TestCollection(), expected2 },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GenerateCollection_ProducesExpectedCodeData))]
|
||||
public void GenerateCollection_ProducesExpectedCode(RazorFileInfoCollection collection, string expected)
|
||||
{
|
||||
// Act
|
||||
var actual = RazorFileInfoCollectionGenerator.GenerateCode(collection);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
private class EmptyCollection : RazorFileInfoCollection
|
||||
{
|
||||
public EmptyCollection()
|
||||
{
|
||||
AssemblyResourceName = "EmptyAssembly";
|
||||
FileInfos = new List<RazorFileInfo>();
|
||||
}
|
||||
}
|
||||
|
||||
private class TestCollection : RazorFileInfoCollection
|
||||
{
|
||||
public TestCollection()
|
||||
{
|
||||
AssemblyResourceName = "TestAssembly";
|
||||
SymbolsResourceName = "SymbolsResource";
|
||||
FileInfos = new List<RazorFileInfo>
|
||||
{
|
||||
new RazorFileInfo
|
||||
{
|
||||
FullTypeName = "SomeType.Name",
|
||||
RelativePath = @"Views/Home/Index.cshtml"
|
||||
},
|
||||
new RazorFileInfo
|
||||
{
|
||||
FullTypeName = "Different.Name",
|
||||
RelativePath = @"Views/Home/Different.cshtml"
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue