Adding ability to qualify the entry point of the main assembly
This commit is contained in:
parent
1e0836167d
commit
1653e56b98
|
|
@ -5,7 +5,15 @@ using Microsoft.AspNetCore.Blazor.Browser.Rendering;
|
|||
|
||||
namespace StandaloneApp
|
||||
{
|
||||
public class Program
|
||||
public class ProgramX
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
new BrowserRenderer().AddComponent<Home>("app");
|
||||
}
|
||||
}
|
||||
|
||||
public class ProgramY
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
<!-- Local alternative to <RunArguments>blazor serve</RunArguments> -->
|
||||
<RunCommand>dotnet</RunCommand>
|
||||
<RunArguments>run --project ../../src/Microsoft.AspNetCore.Blazor.DevHost serve</RunArguments>
|
||||
<StartupObject>StandaloneApp.ProgramY</StartupObject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,13 @@ async function boot() {
|
|||
// Read startup config from the <script> element that's importing this file
|
||||
const allScriptElems = document.getElementsByTagName('script');
|
||||
const thisScriptElem = document.currentScript || allScriptElems[allScriptElems.length - 1];
|
||||
const entryPoint = thisScriptElem.getAttribute('main');
|
||||
if (!entryPoint) {
|
||||
throw new Error('Missing "main" attribute on Blazor Config script tag.');
|
||||
const entryPointDll = thisScriptElem.getAttribute('main');
|
||||
if (!entryPointDll) {
|
||||
throw new Error('Missing "main" attribute on Blazor script tag.');
|
||||
}
|
||||
const entryPointAssemblyName = getAssemblyNameFromUrl(entryPoint);
|
||||
// TODO: should method be a required, non-empty field or just an optional *hint*?
|
||||
const entryPointMethod = thisScriptElem.getAttribute('entry-point');
|
||||
const entryPointAssemblyName = getAssemblyNameFromUrl(entryPointDll);
|
||||
const referenceAssembliesCommaSeparated = thisScriptElem.getAttribute('references') || '';
|
||||
const referenceAssemblies = referenceAssembliesCommaSeparated
|
||||
.split(',')
|
||||
|
|
@ -19,7 +21,7 @@ async function boot() {
|
|||
.filter(s => !!s);
|
||||
|
||||
// Determine the URLs of the assemblies we want to load
|
||||
const loadAssemblyUrls = [entryPoint]
|
||||
const loadAssemblyUrls = [entryPointDll]
|
||||
.concat(referenceAssemblies)
|
||||
.map(filename => `/_framework/_bin/${filename}`);
|
||||
|
||||
|
|
@ -30,7 +32,7 @@ async function boot() {
|
|||
}
|
||||
|
||||
// Start up the application
|
||||
platform.callEntryPoint(entryPointAssemblyName, []);
|
||||
platform.callEntryPoint(entryPointAssemblyName, entryPointMethod, []);
|
||||
}
|
||||
|
||||
boot();
|
||||
|
|
|
|||
|
|
@ -45,11 +45,24 @@ export const monoPlatform: Platform = {
|
|||
return methodHandle;
|
||||
},
|
||||
|
||||
callEntryPoint: function callEntryPoint(assemblyName: string, args: System_Object[]): void {
|
||||
callEntryPoint: function callEntryPoint(assemblyName: string, methodName: string | null, args: System_Object[]): void {
|
||||
// TODO: There should be a proper way of running whatever counts as the entrypoint without
|
||||
// having to specify what method it is, but I haven't found it. The code here assumes
|
||||
// that the entry point is "<assemblyname>.Program.Main" (i.e., namespace == assembly name).
|
||||
const entryPointMethod = monoPlatform.findMethod(assemblyName, assemblyName, 'Program', 'Main');
|
||||
if (!methodName)
|
||||
methodName = assemblyName + ".Program::Main";
|
||||
|
||||
var classAndMethod = methodName.split("::");
|
||||
if (classAndMethod.length != 2)
|
||||
throw new Error("malformed entry point method name; could not resolve class name and method name");
|
||||
|
||||
methodName = classAndMethod[1];
|
||||
const nsAndClass = classAndMethod[0];
|
||||
const lastDot = nsAndClass.lastIndexOf(".");
|
||||
// It's possible the entry point method has no namespace
|
||||
const namespace = lastDot > -1 ? classAndMethod[0].substring(0, lastDot) : "";
|
||||
const className = lastDot > -1 ? classAndMethod[0].substring(lastDot + 1) : classAndMethod[0];
|
||||
const entryPointMethod = monoPlatform.findMethod(assemblyName, namespace, className, methodName);
|
||||
monoPlatform.callMethod(entryPointMethod, null, args);
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
export interface Platform {
|
||||
start(loadAssemblyUrls: string[]): Promise<void>;
|
||||
|
||||
callEntryPoint(assemblyName: string, args: System_Object[]);
|
||||
callEntryPoint(assemblyName: string, assemblyMethod: string | null, args: System_Object[]);
|
||||
findMethod(assemblyName: string, namespace: string, className: string, methodName: string): MethodHandle;
|
||||
callMethod(method: MethodHandle, target: System_Object | null, args: System_Object[]): System_Object;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using Microsoft.AspNetCore.Blazor.Internal.Common.FileProviders;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Mono.Cecil;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
|
|
@ -50,8 +51,17 @@ namespace Microsoft.AspNetCore.Blazor.Build.Core.FileSystem
|
|||
{
|
||||
var template = File.ReadAllText(path);
|
||||
var assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
|
||||
var assemblyEntryPoint = string.Empty;
|
||||
var binFiles = frameworkFileProvider.GetDirectoryContents("/_bin");
|
||||
result = new IndexHtmlFileProvider(template, assemblyName, binFiles);
|
||||
|
||||
using (var asmDef = AssemblyDefinition.ReadAssembly(assemblyPath))
|
||||
{
|
||||
var ep = asmDef.EntryPoint;
|
||||
if (ep != null)
|
||||
assemblyEntryPoint = $"{ep.DeclaringType.FullName}::{ep.Name}";
|
||||
}
|
||||
|
||||
result = new IndexHtmlFileProvider(template, assemblyName, assemblyEntryPoint, binFiles);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,16 +15,23 @@ namespace Microsoft.AspNetCore.Blazor.Build.Core.FileSystem
|
|||
{
|
||||
internal class IndexHtmlFileProvider : InMemoryFileProvider
|
||||
{
|
||||
public IndexHtmlFileProvider(string htmlTemplate, string assemblyName, IEnumerable<IFileInfo> binFiles)
|
||||
: base(ComputeContents(htmlTemplate, assemblyName, binFiles))
|
||||
public IndexHtmlFileProvider(
|
||||
string htmlTemplate,
|
||||
string assemblyName,
|
||||
string assemblyEntryPoint,
|
||||
IEnumerable<IFileInfo> binFiles) : base(ComputeContents(htmlTemplate, assemblyName, assemblyEntryPoint, binFiles))
|
||||
{
|
||||
}
|
||||
|
||||
private static IEnumerable<(string, byte[])> ComputeContents(string htmlTemplate, string assemblyName, IEnumerable<IFileInfo> binFiles)
|
||||
private static IEnumerable<(string, byte[])> ComputeContents(
|
||||
string htmlTemplate,
|
||||
string assemblyName,
|
||||
string assemblyEntryPoint,
|
||||
IEnumerable<IFileInfo> binFiles)
|
||||
{
|
||||
if (htmlTemplate != null)
|
||||
{
|
||||
var html = GetIndexHtmlContents(htmlTemplate, assemblyName, binFiles);
|
||||
var html = GetIndexHtmlContents(htmlTemplate, assemblyName, assemblyEntryPoint, binFiles);
|
||||
var htmlBytes = Encoding.UTF8.GetBytes(html);
|
||||
yield return ("/index.html", htmlBytes);
|
||||
}
|
||||
|
|
@ -48,7 +55,11 @@ namespace Microsoft.AspNetCore.Blazor.Build.Core.FileSystem
|
|||
/// responsible for completing the Blazor boot process.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
private static string GetIndexHtmlContents(string htmlTemplate, string assemblyName, IEnumerable<IFileInfo> binFiles)
|
||||
private static string GetIndexHtmlContents(
|
||||
string htmlTemplate,
|
||||
string assemblyName,
|
||||
string assemblyEntryPoint,
|
||||
IEnumerable<IFileInfo> binFiles)
|
||||
{
|
||||
var resultBuilder = new StringBuilder();
|
||||
|
||||
|
|
@ -86,6 +97,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Core.FileSystem
|
|||
AppendScriptTagWithBootConfig(
|
||||
resultBuilder,
|
||||
assemblyName,
|
||||
assemblyEntryPoint,
|
||||
binFiles,
|
||||
tag.Attributes);
|
||||
|
||||
|
|
@ -123,6 +135,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Core.FileSystem
|
|||
private static void AppendScriptTagWithBootConfig(
|
||||
StringBuilder resultBuilder,
|
||||
string assemblyName,
|
||||
string assemblyEntryPoint,
|
||||
IEnumerable<IFileInfo> binFiles,
|
||||
List<KeyValuePair<string, string>> attributes)
|
||||
{
|
||||
|
|
@ -136,6 +149,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Core.FileSystem
|
|||
attributesDict.Remove("type");
|
||||
attributesDict["src"] = "/_framework/blazor.js";
|
||||
attributesDict["main"] = assemblyNameWithExtension;
|
||||
attributesDict["entry-point"] = assemblyEntryPoint;
|
||||
attributesDict["references"] = referencesAttribute;
|
||||
|
||||
resultBuilder.Append("<script");
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Blazor.Server.Test
|
|||
{
|
||||
// Arrange
|
||||
var instance = new IndexHtmlFileProvider(
|
||||
null, "fakeassembly", Enumerable.Empty<IFileInfo>());
|
||||
null, "fakeassembly", null, Enumerable.Empty<IFileInfo>());
|
||||
|
||||
// Act
|
||||
var file = instance.GetFileInfo("/index.html");
|
||||
|
|
@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Blazor.Server.Test
|
|||
// Arrange
|
||||
var htmlTemplate = "test";
|
||||
var instance = new IndexHtmlFileProvider(
|
||||
htmlTemplate, "fakeassembly", Enumerable.Empty<IFileInfo>());
|
||||
htmlTemplate, "fakeassembly", null, Enumerable.Empty<IFileInfo>());
|
||||
|
||||
// Act
|
||||
var file = instance.GetFileInfo("/index.html");
|
||||
|
|
@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.Blazor.Server.Test
|
|||
// Arrange
|
||||
var htmlTemplate = "test";
|
||||
var instance = new IndexHtmlFileProvider(
|
||||
htmlTemplate, "fakeassembly", Enumerable.Empty<IFileInfo>());
|
||||
htmlTemplate, "fakeassembly", null, Enumerable.Empty<IFileInfo>());
|
||||
|
||||
// Act
|
||||
var directory = instance.GetDirectoryContents(string.Empty);
|
||||
|
|
@ -86,7 +86,7 @@ namespace Microsoft.AspNetCore.Blazor.Server.Test
|
|||
new TestFileInfo("MyApp.ClassLib.dll"),
|
||||
};
|
||||
var instance = new IndexHtmlFileProvider(
|
||||
htmlTemplate, "MyApp.Entrypoint", dependencies);
|
||||
htmlTemplate, "MyApp.Entrypoint", null, dependencies);
|
||||
|
||||
// Act
|
||||
var file = instance.GetFileInfo("/index.html");
|
||||
|
|
@ -120,7 +120,7 @@ namespace Microsoft.AspNetCore.Blazor.Server.Test
|
|||
new TestFileInfo("MyApp.ClassLib.dll"),
|
||||
};
|
||||
var instance = new IndexHtmlFileProvider(
|
||||
htmlTemplate, "MyApp.Entrypoint", dependencies);
|
||||
htmlTemplate, "MyApp.Entrypoint", null, dependencies);
|
||||
|
||||
// Act
|
||||
var file = instance.GetFileInfo("/index.html");
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Blazor.Server.Test
|
|||
public void FindsReferencedAssemblyGraphRealistic()
|
||||
{
|
||||
// Arrange
|
||||
var standaloneAppAssembly = typeof(StandaloneApp.Program).Assembly;
|
||||
var standaloneAppAssembly = typeof(StandaloneApp.ProgramY).Assembly;
|
||||
var provider = new ReferencedAssemblyFileProvider(
|
||||
standaloneAppAssembly.GetName().Name,
|
||||
new ReferencedAssemblyResolver(
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ using Xunit;
|
|||
namespace Microsoft.AspNetCore.Blazor.E2ETest.Tests
|
||||
{
|
||||
public class StandaloneAppTest
|
||||
: ServerTestBase<DevHostServerFixture<StandaloneApp.Program>>
|
||||
: ServerTestBase<DevHostServerFixture<StandaloneApp.ProgramY>>
|
||||
{
|
||||
public StandaloneAppTest(BrowserFixture browserFixture, DevHostServerFixture<StandaloneApp.Program> serverFixture)
|
||||
public StandaloneAppTest(BrowserFixture browserFixture, DevHostServerFixture<StandaloneApp.ProgramY> serverFixture)
|
||||
: base(browserFixture, serverFixture)
|
||||
{
|
||||
Navigate("/", noReload: true);
|
||||
|
|
|
|||
Loading…
Reference in New Issue