parent
62b9db93b6
commit
110ee28e3e
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Framework.Runtime;
|
||||
using Microsoft.Framework.Runtime.Roslyn;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="ICompilerOptionsProvider"/>.
|
||||
/// </summary>
|
||||
public static class CompilationOptionsProviderExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses the <see cref="ICompilerOptions"/> for the current executing application and returns a
|
||||
/// <see cref="CompilationSettings"/> used for Roslyn compilation.
|
||||
/// </summary>
|
||||
/// <param name="compilerOptionsProvider">A <see cref="ICompilerOptionsProvider"/> that reads compiler options.</param>
|
||||
/// <param name="applicationEnvironment">The <see cref="IApplicationEnvironment"/> for the executing application.</param>
|
||||
/// <returns>The <see cref="CompilationSettings"/> for the current application.</returns>
|
||||
public static CompilationSettings GetCompilationSettings(
|
||||
[NotNull] this ICompilerOptionsProvider compilerOptionsProvider,
|
||||
[NotNull] IApplicationEnvironment applicationEnvironment)
|
||||
{
|
||||
return compilerOptionsProvider.GetCompilerOptions(applicationEnvironment.ApplicationBasePath,
|
||||
applicationEnvironment.RuntimeFramework,
|
||||
applicationEnvironment.Configuration)
|
||||
.ToCompilationSettings(applicationEnvironment.RuntimeFramework);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ using Microsoft.CodeAnalysis.CSharp;
|
|||
using Microsoft.CodeAnalysis.Emit;
|
||||
using Microsoft.Framework.Runtime;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
/// <summary>
|
||||
/// A type that uses Roslyn to compile C# content.
|
||||
|
|
@ -29,6 +29,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IApplicationEnvironment _environment;
|
||||
private readonly IAssemblyLoadContext _loader;
|
||||
private readonly ICompilerOptionsProvider _compilerOptionsProvider;
|
||||
|
||||
private readonly Lazy<List<MetadataReference>> _applicationReferences;
|
||||
|
||||
|
|
@ -44,12 +45,14 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
public RoslynCompilationService(IApplicationEnvironment environment,
|
||||
IAssemblyLoadContextAccessor loaderAccessor,
|
||||
ILibraryManager libraryManager,
|
||||
ICompilerOptionsProvider compilerOptionsProvider,
|
||||
IMvcRazorHost host)
|
||||
{
|
||||
_environment = environment;
|
||||
_loader = loaderAccessor.GetLoadContext(typeof(RoslynCompilationService).GetTypeInfo().Assembly);
|
||||
_libraryManager = libraryManager;
|
||||
_applicationReferences = new Lazy<List<MetadataReference>>(GetApplicationReferences);
|
||||
_compilerOptionsProvider = compilerOptionsProvider;
|
||||
_classPrefix = host.MainClassNamePrefix;
|
||||
}
|
||||
|
||||
|
|
@ -60,15 +63,19 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
// map to the source file. If a file does not exist on a physical file system, PhysicalPath will be null.
|
||||
// This prevents files that exist in a non-physical file system from being debugged.
|
||||
var path = fileInfo.PhysicalPath ?? fileInfo.Name;
|
||||
var syntaxTrees = new[] { SyntaxTreeGenerator.Generate(compilationContent, path) };
|
||||
|
||||
var compilationSettings = _compilerOptionsProvider.GetCompilationSettings(_environment);
|
||||
var syntaxTree = SyntaxTreeGenerator.Generate(compilationContent,
|
||||
path,
|
||||
compilationSettings);
|
||||
var references = _applicationReferences.Value;
|
||||
|
||||
var assemblyName = Path.GetRandomFileName();
|
||||
var compilationOptions = compilationSettings.CompilationOptions
|
||||
.WithOutputKind(OutputKind.DynamicallyLinkedLibrary);
|
||||
|
||||
var compilation = CSharpCompilation.Create(assemblyName,
|
||||
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
|
||||
syntaxTrees: syntaxTrees,
|
||||
options: compilationOptions,
|
||||
syntaxTrees: new[] { syntaxTree },
|
||||
references: references);
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
|
|
@ -115,7 +122,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Compilation
|
|||
.First(t => t.Name.
|
||||
StartsWith(_classPrefix, StringComparison.Ordinal));
|
||||
|
||||
return UncachedCompilationResult.Successful(type);
|
||||
return UncachedCompilationResult.Successful(type, compilationContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,48 +5,29 @@ using System.Text;
|
|||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using Microsoft.Framework.Runtime.Roslyn;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
public static class SyntaxTreeGenerator
|
||||
{
|
||||
private static CSharpParseOptions DefaultOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
return CSharpParseOptions.Default
|
||||
.WithLanguageVersion(LanguageVersion.CSharp6);
|
||||
}
|
||||
}
|
||||
|
||||
public static SyntaxTree Generate([NotNull] string text, [NotNull] string path)
|
||||
{
|
||||
return GenerateCore(text, path, DefaultOptions);
|
||||
}
|
||||
|
||||
public static SyntaxTree Generate([NotNull] string text,
|
||||
[NotNull] string path,
|
||||
[NotNull] CSharpParseOptions options)
|
||||
{
|
||||
return GenerateCore(text, path, options);
|
||||
}
|
||||
|
||||
public static SyntaxTree GenerateCore([NotNull] string text,
|
||||
[NotNull] string path,
|
||||
[NotNull] CSharpParseOptions options)
|
||||
[NotNull] CompilationSettings compilationSettings)
|
||||
{
|
||||
var sourceText = SourceText.From(text, Encoding.UTF8);
|
||||
var syntaxTree = CSharpSyntaxTree.ParseText(sourceText,
|
||||
path: path,
|
||||
options: options);
|
||||
options: GetParseOptions(compilationSettings));
|
||||
|
||||
return syntaxTree;
|
||||
}
|
||||
|
||||
public static CSharpParseOptions GetParseOptions(CSharpCompilation compilation)
|
||||
public static CSharpParseOptions GetParseOptions(CompilationSettings compilationSettings)
|
||||
{
|
||||
return CSharpParseOptions.Default
|
||||
.WithLanguageVersion(compilation.LanguageVersion);
|
||||
return new CSharpParseOptions(
|
||||
languageVersion: compilationSettings.LanguageVersion,
|
||||
preprocessorSymbols: compilationSettings.Defines.AsImmutable());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.Framework.Runtime.Roslyn;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
|
|
@ -13,13 +13,13 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
private string _fileFormat;
|
||||
|
||||
protected IReadOnlyList<RazorFileInfo> FileInfos { get; private set; }
|
||||
protected CSharpParseOptions Options { get; private set; }
|
||||
protected CompilationSettings CompilationSettings { get; }
|
||||
|
||||
public RazorFileInfoCollectionGenerator([NotNull] IReadOnlyList<RazorFileInfo> fileInfos,
|
||||
[NotNull] CSharpParseOptions options)
|
||||
[NotNull] CompilationSettings compilationSettings)
|
||||
{
|
||||
FileInfos = fileInfos;
|
||||
Options = options;
|
||||
CompilationSettings = compilationSettings;
|
||||
}
|
||||
|
||||
public virtual SyntaxTree GenerateCollection()
|
||||
|
|
@ -38,7 +38,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
var sourceCode = builder.ToString();
|
||||
var syntaxTree = SyntaxTreeGenerator.Generate(sourceCode,
|
||||
"__AUTO__GeneratedViewsCollection.cs",
|
||||
Options);
|
||||
CompilationSettings);
|
||||
|
||||
return syntaxTree;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.CSharp;
|
|||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Microsoft.Framework.Runtime;
|
||||
using Microsoft.Framework.Runtime.Roslyn;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
|
|
@ -19,24 +20,28 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IMvcRazorHost _host;
|
||||
|
||||
public RazorPreCompiler([NotNull] IServiceProvider designTimeServiceProvider) :
|
||||
public RazorPreCompiler([NotNull] IServiceProvider designTimeServiceProvider,
|
||||
[NotNull] CompilationSettings compilationSettings) :
|
||||
this(designTimeServiceProvider,
|
||||
designTimeServiceProvider.GetRequiredService<IMvcRazorHost>(),
|
||||
designTimeServiceProvider.GetRequiredService<IOptions<RazorViewEngineOptions>>())
|
||||
designTimeServiceProvider.GetRequiredService<IOptions<RazorViewEngineOptions>>(),
|
||||
compilationSettings)
|
||||
{
|
||||
}
|
||||
|
||||
public RazorPreCompiler([NotNull] IServiceProvider designTimeServiceProvider,
|
||||
[NotNull] IMvcRazorHost host,
|
||||
[NotNull] IOptions<RazorViewEngineOptions> optionsAccessor)
|
||||
[NotNull] IOptions<RazorViewEngineOptions> optionsAccessor,
|
||||
[NotNull] CompilationSettings compilationSettings)
|
||||
{
|
||||
_serviceProvider = designTimeServiceProvider;
|
||||
_host = host;
|
||||
|
||||
var appEnv = _serviceProvider.GetRequiredService<IApplicationEnvironment>();
|
||||
_fileSystem = optionsAccessor.Options.FileSystem;
|
||||
CompilationSettings = compilationSettings;
|
||||
}
|
||||
|
||||
protected CompilationSettings CompilationSettings { get; }
|
||||
|
||||
protected virtual string FileExtension { get; } = ".cshtml";
|
||||
|
||||
public virtual void CompileViews([NotNull] IBeforeCompileContext context)
|
||||
|
|
@ -47,7 +52,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
{
|
||||
var collectionGenerator = new RazorFileInfoCollectionGenerator(
|
||||
descriptors,
|
||||
SyntaxTreeGenerator.GetParseOptions(context.CSharpCompilation));
|
||||
CompilationSettings);
|
||||
|
||||
var tree = collectionGenerator.GenerateCollection();
|
||||
context.CSharpCompilation = context.CSharpCompilation.AddSyntaxTrees(tree);
|
||||
|
|
@ -57,14 +62,11 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
protected virtual IReadOnlyList<RazorFileInfo> CreateCompilationDescriptors(
|
||||
[NotNull] IBeforeCompileContext context)
|
||||
{
|
||||
var options = SyntaxTreeGenerator.GetParseOptions(context.CSharpCompilation);
|
||||
var list = new List<RazorFileInfo>();
|
||||
|
||||
foreach (var info in GetFileInfosRecursive(string.Empty))
|
||||
{
|
||||
var descriptor = ParseView(info,
|
||||
context,
|
||||
options);
|
||||
var descriptor = ParseView(info, context);
|
||||
|
||||
if (descriptor != null)
|
||||
{
|
||||
|
|
@ -107,8 +109,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
}
|
||||
|
||||
protected virtual RazorFileInfo ParseView([NotNull] RelativeFileInfo fileInfo,
|
||||
[NotNull] IBeforeCompileContext context,
|
||||
[NotNull] CSharpParseOptions options)
|
||||
[NotNull] IBeforeCompileContext context)
|
||||
{
|
||||
using (var stream = fileInfo.FileInfo.CreateReadStream())
|
||||
{
|
||||
|
|
@ -124,7 +125,9 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
|
||||
if (generatedCode != null)
|
||||
{
|
||||
var syntaxTree = SyntaxTreeGenerator.Generate(generatedCode, fileInfo.FileInfo.PhysicalPath, options);
|
||||
var syntaxTree = SyntaxTreeGenerator.Generate(generatedCode,
|
||||
fileInfo.FileInfo.PhysicalPath,
|
||||
CompilationSettings);
|
||||
var fullTypeName = results.GetMainClassName(_host, syntaxTree);
|
||||
|
||||
if (fullTypeName != null)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
"Microsoft.AspNet.Mvc.Common": { "version": "6.0.0-*", "type": "build" },
|
||||
"Microsoft.AspNet.Mvc.Core": "6.0.0-*",
|
||||
"Microsoft.AspNet.Mvc.Razor.Host": "6.0.0-*",
|
||||
"Microsoft.CodeAnalysis.CSharp": "1.0.0-beta2-*"
|
||||
"Microsoft.Framework.Runtime.Roslyn.Common": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"aspnet50": {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ using Microsoft.AspNet.Mvc.Internal;
|
|||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.OptionDescriptors;
|
||||
using Microsoft.AspNet.Mvc.Razor;
|
||||
using Microsoft.AspNet.Mvc.Razor.Compilation;
|
||||
using Microsoft.AspNet.Mvc.Razor.OptionDescriptors;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Mvc.Routing;
|
||||
|
|
|
|||
|
|
@ -29,14 +29,17 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
public virtual void BeforeCompile(IBeforeCompileContext context)
|
||||
{
|
||||
var appEnv = _appServices.GetRequiredService<IApplicationEnvironment>();
|
||||
var applicationEnvironment = _appServices.GetRequiredService<IApplicationEnvironment>();
|
||||
var compilerOptionsProvider = _appServices.GetRequiredService<ICompilerOptionsProvider>();
|
||||
var compilationSettings = compilerOptionsProvider.GetCompilationSettings(applicationEnvironment);
|
||||
|
||||
var setup = new RazorViewEngineOptionsSetup(appEnv);
|
||||
var setup = new RazorViewEngineOptionsSetup(applicationEnvironment);
|
||||
var sc = new ServiceCollection();
|
||||
sc.ConfigureOptions(setup);
|
||||
sc.AddMvc();
|
||||
|
||||
var viewCompiler = new RazorPreCompiler(BuildFallbackServiceProvider(sc, _appServices));
|
||||
var serviceProvider = BuildFallbackServiceProvider(sc, _appServices);
|
||||
var viewCompiler = new RazorPreCompiler(serviceProvider, compilationSettings);
|
||||
viewCompiler.CompileViews(context);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.TestHost;
|
||||
using RazorWebSite;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||
{
|
||||
// Test to verify compilation options from the application are used to compile
|
||||
// precompiled and dynamically compiled views.
|
||||
public class CompilationOptionsTests
|
||||
{
|
||||
private readonly IServiceProvider _provider = TestHelper.CreateServices(nameof(RazorWebSite));
|
||||
private readonly Action<IApplicationBuilder> _app = new Startup().Configure;
|
||||
|
||||
[Fact]
|
||||
public async Task CompilationOptions_AreUsedByViewsAndPartials()
|
||||
{
|
||||
// Arrange
|
||||
#if ASPNET50
|
||||
var expected =
|
||||
@"This method is running from ASPNET50
|
||||
|
||||
This method is only defined in ASPNET50";
|
||||
#elif ASPNETCORE50
|
||||
var expected =
|
||||
@"This method is running from ASPNETCORE50
|
||||
|
||||
This method is only defined in ASPNETCORE50";
|
||||
#endif
|
||||
var server = TestServer.Create(_provider, _app);
|
||||
var client = server.CreateClient();
|
||||
|
||||
// Act
|
||||
var body = await client.GetStringAsync("http://localhost/ViewsConsumingCompilationOptions/");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, body.Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ using Microsoft.AspNet.Builder;
|
|||
using Microsoft.AspNet.TestHost;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Runtime;
|
||||
using PrecompilationWebSite;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||
|
|
@ -18,8 +19,8 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
public class PrecompilationTest
|
||||
{
|
||||
private static readonly TimeSpan _cacheDelayInterval = TimeSpan.FromSeconds(2);
|
||||
private readonly IServiceProvider _services = TestHelper.CreateServices("PrecompilationWebSite");
|
||||
private readonly Action<IApplicationBuilder> _app = new PrecompilationWebSite.Startup().Configure;
|
||||
private readonly IServiceProvider _services = TestHelper.CreateServices(nameof(PrecompilationWebSite));
|
||||
private readonly Action<IApplicationBuilder> _app = new Startup().Configure;
|
||||
|
||||
[Fact]
|
||||
public async Task PrecompiledView_RendersCorrectly()
|
||||
|
|
@ -37,7 +38,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
|
||||
// We will render a view that writes the fully qualified name of the Assembly containing the type of
|
||||
// the view. If the view is precompiled, this assembly will be PrecompilationWebsite.
|
||||
var assemblyName = typeof(PrecompilationWebSite.Startup).GetTypeInfo().Assembly.GetName().ToString();
|
||||
var assemblyName = typeof(Startup).GetTypeInfo().Assembly.GetName().ToString();
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -142,6 +143,30 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PrecompiledView_UsesCompilationOptionsFromApplication()
|
||||
{
|
||||
// Arrange
|
||||
var assemblyName = typeof(Startup).GetTypeInfo().Assembly.GetName().ToString();
|
||||
#if ASPNET50
|
||||
var expected =
|
||||
@"Value set inside ASPNET50 " + assemblyName;
|
||||
#elif ASPNETCORE50
|
||||
var expected =
|
||||
@"Value set inside ASPNETCORE50 " + assemblyName;
|
||||
#endif
|
||||
|
||||
var server = TestServer.Create(_services, _app);
|
||||
var client = server.CreateClient();
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("http://localhost/Home/PrecompiledViewsCanConsumeCompilationOptions");
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, responseContent.Trim());
|
||||
}
|
||||
|
||||
private static Task TouchFile(string viewsDir, string file)
|
||||
{
|
||||
File.AppendAllText(Path.Combine(viewsDir, file), " ");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,170 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Versioning;
|
||||
using Microsoft.Framework.Runtime;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
public class RoslynCompilationServiceTest
|
||||
{
|
||||
[Fact]
|
||||
public void Compile_ReturnsUncachedCompilationResultWithCompiledContent()
|
||||
{
|
||||
// Arrange
|
||||
var content = @"
|
||||
public class MyTestType {}";
|
||||
var applicationEnvironment = GetApplicationEnvironment();
|
||||
var accessor = GetLoadContextAccessor();
|
||||
var libraryManager = GetLibraryManager();
|
||||
|
||||
var compilerOptionsProvider = new Mock<ICompilerOptionsProvider>();
|
||||
compilerOptionsProvider.Setup(p => p.GetCompilerOptions(applicationEnvironment.ApplicationBasePath,
|
||||
applicationEnvironment.RuntimeFramework,
|
||||
applicationEnvironment.Configuration))
|
||||
.Returns(new CompilerOptions());
|
||||
var mvcRazorHost = new Mock<IMvcRazorHost>();
|
||||
mvcRazorHost.SetupGet(m => m.MainClassNamePrefix)
|
||||
.Returns(string.Empty);
|
||||
|
||||
var compilationService = new RoslynCompilationService(applicationEnvironment,
|
||||
accessor,
|
||||
libraryManager,
|
||||
compilerOptionsProvider.Object,
|
||||
mvcRazorHost.Object);
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(new TestFileInfo { PhysicalPath = "SomePath" }, content);
|
||||
|
||||
// Assert
|
||||
var uncachedResult = Assert.IsType<UncachedCompilationResult>(result);
|
||||
Assert.Equal("MyTestType", result.CompiledType.Name);
|
||||
Assert.Equal(content, result.CompiledContent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_UsesApplicationsCompilationSettings_ForParsingAndCompilation()
|
||||
{
|
||||
// Arrange
|
||||
var content = @"
|
||||
#if MY_CUSTOM_DEFINE
|
||||
public class MyCustomDefinedClass {}
|
||||
#else
|
||||
public class MyNonCustomDefinedClass {}
|
||||
#endif
|
||||
";
|
||||
var applicationEnvironment = GetApplicationEnvironment();
|
||||
var accessor = GetLoadContextAccessor();
|
||||
var libraryManager = GetLibraryManager();
|
||||
|
||||
var compilerOptionsProvider = new Mock<ICompilerOptionsProvider>();
|
||||
compilerOptionsProvider.Setup(p => p.GetCompilerOptions(applicationEnvironment.ApplicationBasePath,
|
||||
applicationEnvironment.RuntimeFramework,
|
||||
applicationEnvironment.Configuration))
|
||||
.Returns(new CompilerOptions { Defines = new[] { "MY_CUSTOM_DEFINE" } });
|
||||
var mvcRazorHost = new Mock<IMvcRazorHost>();
|
||||
mvcRazorHost.SetupGet(m => m.MainClassNamePrefix)
|
||||
.Returns("My");
|
||||
|
||||
var compilationService = new RoslynCompilationService(applicationEnvironment,
|
||||
accessor,
|
||||
libraryManager,
|
||||
compilerOptionsProvider.Object,
|
||||
mvcRazorHost.Object);
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(new TestFileInfo { PhysicalPath = "SomePath" }, content);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result.CompiledType);
|
||||
Assert.Equal("MyCustomDefinedClass", result.CompiledType.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_ReturnsSingleTypeThatStartsWithMainClassNamePrefix()
|
||||
{
|
||||
// Arrange
|
||||
var content = @"
|
||||
public class RazorPrefixType {}
|
||||
public class NotRazorPrefixType {}";
|
||||
var applicationEnvironment = GetApplicationEnvironment();
|
||||
var accessor = GetLoadContextAccessor();
|
||||
var libraryManager = GetLibraryManager();
|
||||
|
||||
var compilerOptionsProvider = new Mock<ICompilerOptionsProvider>();
|
||||
compilerOptionsProvider.Setup(p => p.GetCompilerOptions(applicationEnvironment.ApplicationBasePath,
|
||||
applicationEnvironment.RuntimeFramework,
|
||||
applicationEnvironment.Configuration))
|
||||
.Returns(new CompilerOptions());
|
||||
var mvcRazorHost = new Mock<IMvcRazorHost>();
|
||||
mvcRazorHost.SetupGet(m => m.MainClassNamePrefix)
|
||||
.Returns("RazorPrefix");
|
||||
|
||||
var compilationService = new RoslynCompilationService(applicationEnvironment,
|
||||
accessor,
|
||||
libraryManager,
|
||||
compilerOptionsProvider.Object,
|
||||
mvcRazorHost.Object);
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(new TestFileInfo { PhysicalPath = "SomePath" }, content);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result.CompiledType);
|
||||
Assert.Equal("RazorPrefixType", result.CompiledType.Name);
|
||||
}
|
||||
|
||||
private static ILibraryManager GetLibraryManager()
|
||||
{
|
||||
var fileReference = new Mock<IMetadataFileReference>();
|
||||
fileReference.SetupGet(f => f.Path)
|
||||
.Returns(typeof(string).Assembly.Location);
|
||||
var libraryExport = new Mock<ILibraryExport>();
|
||||
libraryExport.SetupGet(e => e.MetadataReferences)
|
||||
.Returns(new[] { fileReference.Object });
|
||||
libraryExport.SetupGet(e => e.SourceReferences)
|
||||
.Returns(new ISourceReference[0]);
|
||||
|
||||
var libraryManager = new Mock<ILibraryManager>();
|
||||
libraryManager.Setup(l => l.GetAllExports(It.IsAny<string>()))
|
||||
.Returns(libraryExport.Object);
|
||||
return libraryManager.Object;
|
||||
}
|
||||
|
||||
private static IAssemblyLoadContextAccessor GetLoadContextAccessor()
|
||||
{
|
||||
var loadContext = new Mock<IAssemblyLoadContext>();
|
||||
loadContext.Setup(s => s.LoadStream(It.IsAny<Stream>(), It.IsAny<Stream>()))
|
||||
.Returns((Stream stream, Stream pdb) =>
|
||||
{
|
||||
var memoryStream = (MemoryStream)stream;
|
||||
return Assembly.Load(memoryStream.ToArray());
|
||||
});
|
||||
|
||||
var accessor = new Mock<IAssemblyLoadContextAccessor>();
|
||||
accessor.Setup(a => a.GetLoadContext(typeof(RoslynCompilationService).Assembly))
|
||||
.Returns(loadContext.Object);
|
||||
return accessor.Object;
|
||||
}
|
||||
|
||||
private IApplicationEnvironment GetApplicationEnvironment()
|
||||
{
|
||||
var applicationEnvironment = new Mock<IApplicationEnvironment>();
|
||||
applicationEnvironment.SetupGet(a => a.ApplicationName)
|
||||
.Returns("MyApp");
|
||||
applicationEnvironment.SetupGet(a => a.RuntimeFramework)
|
||||
.Returns(new FrameworkName("ASPNET", new Version(5, 0)));
|
||||
applicationEnvironment.SetupGet(a => a.Configuration)
|
||||
.Returns("Debug");
|
||||
applicationEnvironment.SetupGet(a => a.ApplicationBasePath)
|
||||
.Returns("MyBasePath");
|
||||
|
||||
return applicationEnvironment.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,5 +11,10 @@ namespace PrecompilationWebSite.Controllers
|
|||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult PrecompiledViewsCanConsumeCompilationOptions()
|
||||
{
|
||||
return View("~/Views/ViewsConsumingCompilationOptions/Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
@{
|
||||
string message =
|
||||
#if ASPNET50
|
||||
"Value set inside ASPNET50 " + GetType().Assembly.FullName;
|
||||
#elif ASPNETCORE50
|
||||
"Value set inside ASPNETCORE50 " + System.Reflection.IntrospectionExtensions.GetTypeInfo(GetType()).Assembly.FullName;
|
||||
#endif
|
||||
}
|
||||
@message
|
||||
|
|
@ -12,8 +12,16 @@
|
|||
"Microsoft.AspNet.StaticFiles": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"aspnet50": { },
|
||||
"aspnetcore50": { }
|
||||
"aspnet50": {
|
||||
"compilationOptions": {
|
||||
"define": [ "CUSTOM_ASPNET50_DEFINE" ]
|
||||
}
|
||||
},
|
||||
"aspnetcore50": {
|
||||
"compilationOptions": {
|
||||
"define": [ "CUSTOM_ASPNETCORE50_DEFINE" ]
|
||||
}
|
||||
}
|
||||
},
|
||||
"webroot": "wwwroot"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace RazorWebSite.Controllers
|
||||
{
|
||||
// Views returned by this controller use #ifdefs for defines specified in project.json
|
||||
// The intent of this controller is to verify that view compilation uses the app's compilation settings.
|
||||
public class ViewsConsumingCompilationOptionsController : Controller
|
||||
{
|
||||
public ViewResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace RazorWebSite
|
||||
{
|
||||
public class FrameworkSpecificHelper
|
||||
{
|
||||
public string ExecuteOperation()
|
||||
{
|
||||
#if ASPNET50
|
||||
return "This method is running from ASPNET50";
|
||||
#elif ASPNETCORE50
|
||||
return "This method is running from ASPNETCORE50";
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ASPNET50_CUSTOM_DEFINE
|
||||
public string ExecuteAspNet50Operation()
|
||||
{
|
||||
return "This method is only defined in ASPNET50";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASPNETCORE50_CUSTOM_DEFINE
|
||||
public string ExecuteAspNetCore50Operation()
|
||||
{
|
||||
return "This method is only defined in ASPNETCORE50";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ namespace RazorWebSite
|
|||
services.AddMvc(configuration);
|
||||
services.AddTransient<InjectedHelper>();
|
||||
services.AddTransient<TaskReturningService>();
|
||||
services.AddTransient<FrameworkSpecificHelper>();
|
||||
services.Configure<RazorViewEngineOptions>(options =>
|
||||
{
|
||||
var expander = new LanguageViewLocationExpander(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
@inject FrameworkSpecificHelper MyHelper
|
||||
@MyHelper.ExecuteOperation()
|
||||
@Html.Partial("_Partial")
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
@inject FrameworkSpecificHelper MyHelper
|
||||
@{
|
||||
string value =
|
||||
#if ASPNET50_CUSTOM_DEFINE
|
||||
MyHelper.ExecuteAspNet50Operation();
|
||||
#endif
|
||||
#if ASPNETCORE50_CUSTOM_DEFINE
|
||||
MyHelper.ExecuteAspNetCore50Operation();
|
||||
#endif
|
||||
}
|
||||
@value
|
||||
|
|
@ -12,8 +12,16 @@
|
|||
"Microsoft.AspNet.StaticFiles": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"aspnet50": { },
|
||||
"aspnetcore50": { }
|
||||
"aspnet50": {
|
||||
"compilationOptions": {
|
||||
"define": [ "ASPNET50_CUSTOM_DEFINE" ]
|
||||
}
|
||||
},
|
||||
"aspnetcore50": {
|
||||
"compilationOptions": {
|
||||
"define": [ "ASPNETCORE50_CUSTOM_DEFINE" ]
|
||||
}
|
||||
}
|
||||
},
|
||||
"webroot": "wwwroot"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue