Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an application part factory for an assembly that contains controllers and views. #30481

Merged
merged 1 commit into from
Mar 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// 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 System.Linq;
using System.Reflection;

namespace Microsoft.AspNetCore.Mvc.ApplicationParts
{
/// <summary>
/// Configures an <see cref="ApplicationPart" /> that contains controllers, as well as Razor views and Pages.
/// <para>
/// Combines the results of <see cref="DefaultApplicationPartFactory.GetApplicationParts(Assembly)"/> and
/// <see cref="CompiledRazorAssemblyApplicationPartFactory.GetApplicationParts(Assembly)"/>. This part factory
/// may be used if Razor views or Razor Pages are compiled in to with other types including controllers.
/// </para>
/// </summary>
public sealed class ConsolidatedAssemblyApplicationPartFactory : ApplicationPartFactory
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spicy thought, instead of doing this, we could code-generate this class as part of the compiler work and this way we don't need another public type here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused as to how this get wires up right now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spicy thought, instead of doing this, we could code-generate this class as part of the compiler work

Hmmm....what's the benefit of doing this?

I'm confused as to how this get wires up right now.

The ConsolidatedAssemblyApplicationPartFactory isn't used anywhere at the moment. Eventually, we'll be including the compiled views in the application assembly, which will be stamped stamped with a ConsolidatedAssembly attribute, and then using this API to look for RazorCompiledItems that are baked into the app assembly, in addition to it's own types.

@pranavkm Correct me if I got any details wrong.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@captainsafia is spot on.

My suggestion is we don't need a public type, we can just codegen one of these puppies per assembly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏽 on @captainsafia's analysis.

@javiercn I'm not sure what code-gening this gets us. Is it to avoid adding a public type?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also because that way, changes in the mechanics of how it works are isolated to the compiler instead of being a concern shared by the runtime

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I signed-off, but just want you to think about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how it works are isolated to the compile

The downside is that the compiler would need to be aware of the app's tfm if we have to change the implementation. We're currently not planning to ship the source generator thru a runtime pack. Once we decide to use it, all of the code it generates is driven by RazorLanguageVersion, not by the app's tfm.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let me bring this up during API review. I'm kinda partial to just having the type in the framework, but I'll see how other folks feel about this.

{
/// <inheritdoc />
public override IEnumerable<ApplicationPart> GetApplicationParts(Assembly assembly)
Copy link
Member

@rynowak rynowak Feb 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spicy question - why do you need this boy VS adding this functionality to CompiledRazorAssemblyApplicationPartFactory? I can't think of a case today where someone has controllers in their existing razor code.

You could also simplify this other way by just building the Razor Page discovery into the default case.

Basically what I'm saying is that on reflection, it seems like this area is overdesigned a bit. Someone (wonder who's to blame) seemed to really be in love with this idea of combining codegen+metadata to configure runtime behaviour when they built this, and maybe it could just all be simpler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @rynowak for the feedback. It feels like either of those options has slightly higher inherent breaking change risk or work to make work compared to just adding an additional API. Particularly given that this API is a bit tucked away and MVC is a wasteland of fun APIs, this didn't seem like overkill. We'll stick with the new type for now, we have time until 6.0 ship if we start feeling differently about it.

{
return Enumerable.Concat(
DefaultApplicationPartFactory.GetDefaultApplicationParts(assembly),
CompiledRazorAssemblyApplicationPartFactory.GetDefaultApplicationParts(assembly));
}
}
}
3 changes: 3 additions & 0 deletions src/Mvc/Mvc.Razor/src/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
#nullable enable
Microsoft.AspNetCore.Mvc.ApplicationParts.ConsolidatedAssemblyApplicationPartFactory
Microsoft.AspNetCore.Mvc.ApplicationParts.ConsolidatedAssemblyApplicationPartFactory.ConsolidatedAssemblyApplicationPartFactory() -> void
~override Microsoft.AspNetCore.Mvc.ApplicationParts.ConsolidatedAssemblyApplicationPartFactory.GetApplicationParts(System.Reflection.Assembly assembly) -> System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPart>