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

Re-introduce runtime code generation #3669

Merged
merged 6 commits into from
Dec 1, 2017

Conversation

ReubenBond
Copy link
Member

No description provided.

@ReubenBond ReubenBond added this to the 2.0.0 milestone Nov 14, 2017
@ReubenBond ReubenBond force-pushed the feature-runtime-codegen branch from 9c75068 to da21d5f Compare November 14, 2017 19:06
@jdom
Copy link
Member

jdom commented Nov 14, 2017

This will conflict with #3595. Which one should go in first? I assume that @benjaminpetit's is ready to be merged

public class RuntimeCodeGenTests
{
[Fact]
public void RuntimeCodeGenAddsSupportClasses()
Copy link
Member

Choose a reason for hiding this comment

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

Is it worth adding a functional that starts a silo and verifies the grain and serialization works?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure thing, will do

@jdom
Copy link
Member

jdom commented Nov 14, 2017

Although what you are solving by not requiring a SerializationManager for codegen is what @benjaminpetit wanted to do eventually, but couldn't do yet, so he hacked around it... maybe it's better to merge this one first and have him rebase on this one? I'm fine with whatever you guys decide. Although from what I see about the extension methods discussion this PR might take longer?

tempPartManager.AddFeatureProvider(new BuiltInTypesSerializationFeaturePopulator());

var codeGenerator = new RoslynCodeGenerator(tempPartManager, new NullLoggerFactory());
var generatedAssembly = codeGenerator.GenerateAndLoadForAssemblies(manager.Assemblies);
Copy link
Member

Choose a reason for hiding this comment

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

Does it mean that codegen is run immediately? Shouldn't it wait until a specific point in time just before building the container, so that all the different codegen tasks occur together? Because if I use the WithCodeGeneration extension method multiple times, it will run multiple times. Or did I misunderstand this?

Copy link
Member Author

@ReubenBond ReubenBond Nov 15, 2017

Choose a reason for hiding this comment

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

That's correct - code gen will run immediately, but not necessarily for one assembly at a time. The user has a degree of control over it.

In the following code, codegen is executed twice: once for IMyGrain's asm and MyGrain's asm and then again for whatever asms are in the app base dir. The second execution will see the code generated by the first, so it won't double-generate.

.ConfigureApplicationPartManager(parts =>
{
    parts.AddApplicationPart(typeof(IMyGrain).Assembly)
         .AddApplicationPart(typeof(MyGrain).Assembly)
         .WithCodeGeneration();
    parts.AddFromApplicationBaseDirectory().WithCodeGeneration();
});

The above code could execute codegen only once if the methods were all chained together instead of starting again from parts.

Does that seem alright or would you prefer that all actions are queued up and executed only during Build()? That would add some complexity.

Copy link
Member

Choose a reason for hiding this comment

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

I guess it's fine if there is a way to chain everything and then execute once. And if they don't double-generate even when executing twice, then that's harmless anyway.

@ReubenBond ReubenBond force-pushed the feature-runtime-codegen branch from c343a03 to 3827e6c Compare November 17, 2017 03:31
@ReubenBond ReubenBond changed the title Expose runtime code generation through ApplicationPartManager [WIP] Expose runtime code generation through ApplicationPartManager Nov 17, 2017
@ReubenBond ReubenBond force-pushed the feature-runtime-codegen branch 7 times, most recently from 99681bb to 0ad25cf Compare November 21, 2017 11:52
@ReubenBond
Copy link
Member Author

@dotnet-bot test functional

@ReubenBond ReubenBond changed the title [WIP] Expose runtime code generation through ApplicationPartManager Expose runtime code generation through ApplicationPartManager Nov 21, 2017
@ReubenBond ReubenBond force-pushed the feature-runtime-codegen branch 2 times, most recently from 9aa25b9 to 3f1cb95 Compare November 29, 2017 12:18
@ReubenBond
Copy link
Member Author

@dotnet-bot test functional

/// </summary>
/// <param name="manager">The builder.</param>
/// <returns>A builder with support parts added.</returns>
public static IApplicationPartManagerWithAssemblies WithCodeGeneration(this IApplicationPartManagerWithAssemblies manager)
Copy link
Member

Choose a reason for hiding this comment

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

should the return be void. Otherwise it would be confusing what would happen if you keep chaining, wouldn't it?

Copy link
Member Author

Choose a reason for hiding this comment

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

you can call WithCodeGeneration().WithReferences(), for example - but we could make it void and force the order. What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

But what would that do? it's not clear to me

Copy link
Member Author

Choose a reason for hiding this comment

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

It should include those assemblies, generate code for them, and also include their references

t == typeof(string) ||
t == typeof(DateTime) ||
t == typeof(Decimal) ||
(t.IsArray && t.GetElementType().GetTypeInfo().IsOrleansPrimitive());
Copy link
Member

Choose a reason for hiding this comment

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

You can probably avoid calling GetTypeInfo() since the extension method is now on Type

foreach (var parameter in typeInfo.GenericTypeParameters)
{
foreach (var constraint in parameter.GetTypeInfo().GetGenericParameterConstraints())
{
if (IsSpecialClass(constraint)) return false;
if (constraint == typeof(Array) || constraint == typeof(Delegate) || constraint == typeof(Enum)) return false;
Copy link
Member

Choose a reason for hiding this comment

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

You dropped ValueType when inlining. Was it by design?

Copy link
Member Author

Choose a reason for hiding this comment

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

It is: it was supposed to tell us what types cannot be used as generic constraints in C#, but ValueType can (T : struct).

@@ -34,6 +34,7 @@ public KnownAssemblyAttribute(string assemblyName)
/// serializable.
/// </summary>
/// <remarks>This is equivalent to specifying <see cref="KnownTypeAttribute"/> for all types.</remarks>
[Obsolete("This property is no longer supported. Serializers will be generated for all accessible types.")]
Copy link
Member

Choose a reason for hiding this comment

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

What's the reason for this change?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's simpler and less error prone to just consider all types in the few assemblies we're processing

Copy link
Member

Choose a reason for hiding this comment

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

But could be a lot more expensive now that runtime codegen is back, right? I'm not pushing back, just trying to understand

Copy link
Member Author

Choose a reason for hiding this comment

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

It could be, since we need to perform accessibility checks for more types now. We cache those checks, though, so it shouldn't be an issue.

/// <param name="builder">The builder.</param>
/// <param name="configure">The configuration delegate.</param>
/// <returns>The builder.</returns>
public static IClientBuilder ConfigureApplicationPartManager(this IClientBuilder builder, Action<IApplicationPartManager> configure)
Copy link
Member

Choose a reason for hiding this comment

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

How about dropping Manager and just have ConfigureApplicationParts(...)? It is using the manager under the hoods, but the user is configuring which parts the app will use (and of course it's less verbose)

/// <param name="builder">The builder.</param>
/// <param name="assembly">The assembly.</param>
/// <returns>The builder.</returns>
public static ISiloHostBuilder AddApplicationPart(this ISiloHostBuilder builder, Assembly assembly)
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 on the fence with this one. Do you envision this to be the most common case? Otherwise to make the jump to add references too for example, then it's a lot different, and maybe the best is to get them to use the fluent interface in the first place.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm on the fence, too - should we just axe it? Shortcuts like this can be added later if we want, so maybe it's better to be conservative.

Copy link
Member

Choose a reason for hiding this comment

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

My vote is yes: let's axe it for now

Copy link
Member

Choose a reason for hiding this comment

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

Should I wait for this change or you think we should keep it then?

@ReubenBond ReubenBond force-pushed the feature-runtime-codegen branch from c5c498e to 96cd529 Compare December 1, 2017 03:10
@jdom jdom changed the title Expose runtime code generation through ApplicationPartManager Re-introduce runtime code generation Dec 1, 2017
@jdom jdom merged commit f501f75 into dotnet:master Dec 1, 2017
@github-actions github-actions bot locked and limited conversation to collaborators Dec 9, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants