Introducing C# Source Generators

Phillip Carter

Phillip

We’re pleased to introduce the first preview of Source Generators, a new C# compiler feature that lets C# developers inspect user code and generate new C# source files that can be added to a compilation. This is done via a new kind of component that we’re calling a Source Generator.

To get started with Source Generators, you’ll need to install the latest .NET 5 preview and the latest Visual Studio previewNote: to build a source generator, you currently require Visual Studio. This will change in the next .NET 5 preview.

What is a Source Generator?

Unless you’ve been closely following every prototype and proposal related to the C# language and compiler, then there’s a good chance you’re asking, “What is a Source Generator” right now. A Source Generator is a piece of code that runs during compilation and can inspect your program to produce additional files that are compiled together with the rest of your code.

A Source Generator is a new kind of component that C# developers can write that lets you do two major things:

  1. Retrieve a Compilation object that represents all user code that is being compiled. This object can be inspected and you can write code that works with the syntax and semantic models for the code being compiled, just like with analyzers today.
  2. Generate C# source files that can be added to a Compilation object during the course of compilation. In other words, you can provide additional source code as input to a compilation while the code is being compiled.

When combined, these two things are what make Source Generators so useful. You can inspect user code with all of the rich metadata that the compiler builds up during compilation, then emit C# code back into the same compilation that is based on the data you’ve analyzed! If you’re familiar with Roslyn Analyzers, you can think of Source Generators as analyzers that can emit C# source code.

Source generators run as a phase of compilation visualized below:

Image Picture1

A Source Generator is a .NET Standard 2.0 assembly that is loaded by the compiler along with any analyzers. It is usable in environments where .NET Standard components can be loaded and run.

Now that you know what a Source Generator is, let’s go through some of the scenarios they can improve.

Example scenarios that can benefit from Source Generators

The most important aspect of a Source Generator isn’t what it is, but what it can enable.

Today, there are three general approaches to inspecting user code and generating information or code based on that analysis used by technologies today: runtime reflection, IL weaving, and juggling MSBuild tasks. Source Generators can be an improvement over each approach.

Runtime reflection is a powerful technology that was added to .NET a long time ago. There are countless scenarios for using it. A very common scenario is to perform some analysis of user code when an app starts up and use that data to generate things.

For example, ASP.NET Core uses reflection when your web service first runs to discover constructs you’ve defined so that it can “wire up” things like controllers and razor pages. Although this enables you to write straightforward code with powerful abstractions, it comes with a performance penalty at runtime: when your web service or app first starts up, it cannot accept any requests until all the runtime reflection code that discovers information about your code is finished running! Although this performance penalty is not enormous, it is somewhat of a fixed cost that you cannot improve yourself in your own app.

With a Source Generator, the controller discovery phase of startup could instead happen at compile time by analyzing your source code and emitting the code it needs to “wire up” your app. This could result in some faster startup times, since an action happening at runtime today could get pushed into compile time.

Source Generators can improve performance in ways that aren’t limited to reflection at runtime to discover types as well. Some scenarios involve calling the MSBuild C# task (called CSC) multiple times so they can inspect data from a compilation. As you might imagine, calling the compiler more than once affects the total time it takes to build your app! We’re investigating how Source Generators can be used to obviate the need for juggling MSBuild tasks like this, since Source generators don’t just offer some performance benefits, but also allows tools to operate at the right level of abstraction.

Another capability Source Generators can offer is obviating the use of some “stringly-typed” APIs, such as how ASP.NET Core routing between controllers and razor pages work. With a Source Generator, routing can be strongly typed with the necessary strings being generated as a compile-time detail. This would reduce the amount of times a mistyped string literal leads to a request not hitting the correct controller.

As we flesh out the API and experience writing Source Generators more, we anticipate more scenarios to become evident. We’re also planning on working with partner teams to help them adopt Source Generators if it improves their core scenarios.

Source Generators and Ahead of Time (AOT) Compilation

Another characteristic of Source Generators is that they can help remove major barriers to linker-based and AOT (ahead-of-time) compilation optimizations. Many frameworks and libraries make heavy use of reflection or reflection-emit, such as System.Text.Json, System.Text.RegularExpressions, and frameworks like ASP.NET Core and WPF that discover and/or emit types from user code at runtime.

We’ve also identified that many of the top NuGet packages people make heavy use of reflection to discover types at runtime. Incorporating these packages is essential for most .NET apps, so the “linkability” and ability for your code to make use of AOT compiler optimizations is greatly affected. We’re looking forward to working with our wonderful OSS community to see how these packages could use source generators and improve the overall .NET ecosystem.

Hello World, Source Generator edition

All the previous examples of source generators mentioned earlier are pretty complex. Let’s go through a very basic one to show some of the key pieces you’ll need to write your own Source Generator.

The goal is to let users who have installed this Source Generator always have access to a friendly “Hello World” message and all syntax trees available during compilation. They could invoke it like this:

Over time, we’ll make getting started a lot easier in tools with templates. For now, here’s how to do it manually:

1. Create a .NET Standard library project that looks like this:

The key pieces of this is that the project can generate a NuGet package and it depends on the bits that enable Source Generators.

2. Modify or create a C# file that specifies your own Source Generator like so:

You’ll need to apply the Microsoft.CodeAnalysis.Generator attribute and implement the Microsoft.CodeAnalysis.ISourceGenerator interface.

3. Add generated source code to the compilation!

4. Add the source generator from a project as an analyzer and add preview to the LangVersion to the project file like this:

If you’ve written Roslyn Analyzers before, the local development experience should be similar.

When you write your code in Visual Studio, you’ll see that the Source Generator runs and the generated code is available to your project. You can now access it as if you had created it yourself:

Note: you will currently need to restart Visual Studio to see IntelliSense and get rid of errors with the early tooling experience

There are many more things you can do with Source Generators than just something simple like this:

  • Automatically implement interfaces for classes with an attribute attached to them, such as INotifyPropertyChanged
  • Generate settings files based on data inspected from a SourceGeneratorContext
  • Serialize values from classes into JSON strings
  • etc.

The Source Generators Cookbook goes over some of these examples with some recommended approaches to solving them.

Additionally, we have a set of samples available on GitHub that you can try on your own.

As mentioned earlier, we’re working on making the experience authoring and using Source Generators better in tooling, such as adding templates, allowing for seamless IntelliSense and navigation, debugging, and improving responsiveness and performance in Visual Studio when generating source files.

Source Generators are in preview

As mentioned earlier in this post, this is the first preview of Source Generators. The intention of releasing this first preview is to let library authors try out the feature and give us feedback on what’s missing and what needs to change. From preview to preview, there may be changes in the API and characteristics of source generators. We intend on shipping Source Generators as GA with C# 9, and sometime later this year we intend on stabilizing the API and features it provides.

Calling all C# library developers: try it out!

If you own a .NET library written in C#, now is a great time to evaluate Source Generators and see if they’re a good fit. There’s a good chance that if your library makes heavy use of reflection, you’ll benefit in some way.

To help with that, we recommend reading the following docs:

Give us your feedback and let us know what you need! We’d love to learn more about how you think Source Generators could improve your code, and what you feel is missing or needs changing.

What’s next for Source Generators

This first preview is is exactly that: a first preview. There is a basic editing experience in Visual Studio, but it is not what we would consider “1.0 quality” right now. We may explore a few different designs over time before we commit to a particular one. One of the biggest areas of focus between now and the .NET 5 release will be improving the editing experience for Source Generators. Additionally, we expect to modify the API to accommodate feedback from partner teams and our OSS community.

Additionally, we’ll ensure a good experience for how Source Generators are distributed. We’re currently designing them to be very similar to Analyzers that can be shipped alongside a package. They currently use the Analyzer infrastructure to handle configuration in editor tooling.

FAQ

Below is a list of questions we anticipate some people might have. We’ll update this list with more questions as they come.

How do Source Generators compare to other metaprogramming features like macros or compiler plugins?

Source Generators are a form of metaprogramming, so it’s natural to compare them to similar features in other languages like macros. The key difference is that Source Generators don’t allow you _rewrite_ user code. We view this limitation as a significant benefit, since it keeps user code predictable with respect to what it actually does at runtime. We recognize that rewriting user code is a very powerful feature, but we’re unlikely to enable Source Generators to do that.

How do Source Generators compare with Type Providers in F#?

If you’re an F# programmer (or familiar with the language), then you might have heard of Type Providers. Source Generators were inspired in part by Type Providers, but there are several differences that make them distinct. The main difference is that Type Providers are a part of the F# language proper and emit types, properties, and methods in-memory based on an external source. Source Generators are a compiler feature that analyzes C# source code, optionally with other files, emits C# source code to include back into a compilation.

Should I delete all my reflection code?

No! Reflection is an incredibly useful tool to use. Reflection does present some performance and “linkability” challenges that can be solvable with Source Generators in some scenarios. We recommend carefully evaluating if Source Generators fit your scenario.

How are Source Generators this different from analyzers?

Source Generators are similar to analyzers, since both are compiler features that let you plug into a compilation. The key difference is that analyzers ultimately emit diagnostics that can be used to associate with a code fix. Source Generators ultimately emit C# source code that is added to a compilation. There are several other differences discussed in the design document.

Can I modify/rewrite existing code with a Source Generator?

No. As mentioned earlier, Source Generators do not allow you to rewrite user source code. We do not intend on allowing them to this. They can only augment a compilation by adding C# source files to it.

When will Source Generators be out of preview?

We intend on shipping Source Generators with C# 9. However, in the event that they aren’t ready in time, we’ll keep them in preview and ensure that users need to opt in to use them.

Can I change the TFM in a Source Generator?

Technically, yes. Source Generators are .NET Standard 2.0 components, and like any project you can change the TFM. However, they only support being loaded into consuming projects as .NET Standard 2.0 components today.

Will Source Generators come to Visual Basic or F#?

Source Generators are currently a C# only feature. Because this is the first preview, there are many things that can change between now and the released version. We do not intend on adding Source Generators to Visual Basic at this time. If you’re an F# developer and want to see this feature added, please search the suggestions or file a new one in the F# language suggestion repository.

Do Source Generators introduce compatibility concerns for libraries?

This depends on how libraries are authored. Since VB and F# currently don’t support Source Generators, library authors should avoid designing their features such that they require a Source Generator. Ideally, features have fallbacks to runtime reflection and/or reflection emit. This is something that library authors will need to careful consider before adopting Source Generators. We expect most library authors will use Source Generators to augment – rather than replace – current experiences for C# developers.

Why do I not get IntelliSense for generated code? Why does Visual Studio say there’s an error even though it builds?

You will need to restart Visual Studio after building the source generator to make errors go away and IntelliSense appear for generated source code. After you do that, things will work. Currently, Visual Studio integration is very early on. This current behavior will change in the future so that you don’t need to restart Visual Studio.

Can I debug or navigate to generated source in Visual Studio?

Eventually, we’ll support navigation and debugging of generated source in Visual Studio. It is not yet supported in this early preview stage.

How do I ship my own Source Generator?

Source Generators can be shipped as NuGet packages, just like Analyzers today. In fact, they use the same “plumbing” as Analyzers. If you’ve ever shipped an Analyzer, then you can easily ship a Source Generator.

Will there be Microsoft-authored Source Generators?

Eventually, yes. But this is still the first preview of the technology, and a lot of things may need to change to accommodate various scenarios. There is currently no timeline for when Microsoft-authored Source Generators are available.

Why do I need to use the Preview LangVersion to consume a Source Generator?

Although Source Generators are not technically a C# language feature, they are in preview. Rather than introduce a new setting just for Source Generators, we decided it would be easier to just use the existing switch that enables preview language features for the C# compiler.

 

Cheers, and happy source generation!

107 comments

Leave a comment

  • Avatar
    Jeremy Morton

    This is a very promising feature. I’ve been maintaining a code generator for years. We switched over to .Net Core and being a DotNetCliTool, then over to a local tool, and the amount of trial and error and refinement to reasonably well plug into building, cleaning, rebuilding, incremental building, etc. was very high. It will be great if this made all that MSBuild file work and experimentation a thing of the past.

  • Avatar
    Nobuyuki Iwanaga

    Can I reference an analyzer by project reference instead of path reference?

    That is

    Include="path-to-source-generator.csproj"

    instead of

    Include="path-to-source-generator/Debug/netstandard2.0/SourceGeneratorName.dll"
      • Avatar
        Damian Wyka

        Sorry that i reply to you here instead under your post on my suggestion but blog somehow removed reply button under your post there on mobile

        What do you think about allowing insertions of pure method calls into existing code if this concept ever makes entrance to .net world? If im not mistaken pure means no side effects and as such they wouldnt hugely affect behaviour of already written code

        This of course greatly limits what you can do but it would at least enable some scenarios involving console output (simple autoprofiling for example maybe more but i didnt think about it very thoroughly)

        This suggestion is direct response to what you have wrote:

        That said, we’re still pretty firm about the stance regarding no rewriting of user code. One of the principles we have with this feature (and that C# tends to abide by pretty well) is that you get what you write (YGWYW?) – the compiler doesn’t try to do fancy things and rewrite a chunk of code into more obscure patterns that you would not have written yourself.

        Its a shame it wont be allowed but i can somewhat understand the unwillingness to mess with problems that can pop when auto modifying existing code and behaviour

  • Joshua DeLong
    Joshua DeLong

    I see someone making the code for this almost immediately. I think over the years of .NET this has been one of the most searched features.
    “Automatically implement interfaces for classes with an attribute attached to them, such as INotifyPropertyChanged”

      • Avatar
        Chris SienkiewiczMicrosoft logo

        Conceptually T4 and source generators are similar; however source generators run inside the compiler pipeline, which means you can do things like introspecting the users code to make decisions about what to emit.

        Because they are part of the compiler pipeline, source generators are supported everywhere the compiler is, including inside Visual Studio, command line builds and CI. T4 on the other hand has limited support outside of Visual Studio, and must be manually run before building.

        Like T4 source generators do *not* allow for re-writing user code. Source generators are strictly additional source only.

  • Avatar
    Martin Sedlmair

    That’s really awesome. Nevertheless I would really appreciate if code rewrites would be possible although I see your potential risks.
    I also don’t see how source generators can add for example INotifyPropertyChanged implementations if you cannot rewrite your code.
    As an example I was assuming that in this case I add a [NotifyChanged] attribute the behavior is weaved into the object that has the attribute,
    but if you cannot rewrite the code, how would this be possible?

    • Avatar
      Chris SienkiewiczMicrosoft logo

      The tooling and compiler support are currently in preview, and require .NET 5 and the latest visual studio. We expect generators to be able to target lower level runtimes and language versions, but ultimately shipped compilers and tools can’t be retroactively made to understand generators.

  • Avatar
    Maksim Kislyakov

    That is an extremely cool feature! About code rewriting. I totally understand why it is disallowed. But what if it would be implemented like so: If code wants to rewrite another source file just copy that source file into /obj directory(which is usually gitignored) and let code do its things with copy. Lastly, you will need to hide the original file from compiler, but include copy from /obj.
    Something like
    Compile Exclude=”A.cs”
    Compile Include=”obj/A.cs”

    This way original source files are kept safe in scm and when you clone fresh copy codegen will just generate a new ‘dirty’ mirror of necessary files.

    • Avatar
      Haymo Kutschbach

      I assume, the concerns about the ability to rewrite code is not so much a technical issue (how to retain the original user code during compilation). Rather, the fact is concerning that it would change the semantics of the user code. It would make it harder for the user to understand what is going on in her app. And it may introduce issues for the debugging experience (which should be not unsolvable, though)…

      • Avatar
        Chris SienkiewiczMicrosoft logo

        Amongst others, a major pain point with code rewriting is the ordering problem. If you have two generators by different authors, who both want to modify the same piece of source, how do they interact? Does one run, then the other see the already modified source? Do both run on the original source, and have some kind of conflict resolution process? Do we error out and say you can’t use these generators together?

        Ultimately we think we can still enable a very large range of scenarios with the current design, without having to design around these incredibly difficult problems. If you have scenarios that can only be achieved via re-writing we’re interested to hear them; feel free to file a GitHub issue explaining the scenario.

        • Avatar
          Damian Wyka

          The problem you mentioned could be solved by providing window with list of generators in order of execution and let us reorder by drag and drop

          This is how unity3d solved the problem with order dependent scripts

          The lack of even limited support for rewrite (ie. Only additions no modifications – eg no supplying extra parameters to existing method calls – nor removals) blocks things like clean method interception

          Other than that this is great autogenerating inotifypropertychanged alone is very welcome

          • Phillip Carter
            Phillip CarterMicrosoft logo

            Interesting suggestion! This also has a precedent in all F# tooling, where the ordering of files carries semantic meaning since in F# things are declare-before-use. So there’s definitely some prior art to consider for something like this if we needed some way for users to speficy an order in which to run generators.

            That said, we’re still pretty firm about the stance regarding no rewriting of user code. One of the principles we have with this feature (and that C# tends to abide by pretty well) is that you get what you write (YGWYW?) – the compiler doesn’t try to do fancy things and rewrite a chunk of code into more obscure patterns that you would not have written yourself. This extends to Source Generators, where we want to still preserve the notion that the code you’ve written will generally execute as you’ve written it. This does hamstring the feature in a sense, since it doesn’t allow for some of the fancier libraries that exist in other languages with a macro system. But we feel that this is a tradeoff worth taking.

      • Avatar
        Olivier Jacot-Descombes

        If we have more than one generator (e.g. from NuGet packages) and they all want to generate a file named *.generated.cs, we have a problem. We could introduce a naming convention which would include a generator designation like *.notify.generated.cs

    • Avatar
      Chris SienkiewiczMicrosoft logo

      Yes, the expectation is that generators can produce source that targets down level runtimes and language versions, but you’ll still need a .NET 5 version of the compiler to do the actual compilation and generation.

      • Avatar
        JesperTreetop

        That’s fine, and this way it’s in line with e.g. nullable reference types in C# 8 being available to .NET Core 2.1 LTS, or even going back so far as LINQ being available to .NET Framework 2.0 if you supplied your own implementation, Caller info attributes if you supplied your own attributes, and so on. This was confusing in the post because it wasn’t clear whether you needed references in the project which could have been .NET 5 only and up, especially since there are temporary differences with preview packages.

        • Avatar
          JesperTreetop

          Oh, I didn’t realize that a generator was a separate project. I thought a .cs file in the same project as the one the generated code is emitted into was designated as an Analyzer/Generator within the project file. Well, that clears it up, and would more or less take special effort to make it non-backwards compatible framework-wise since it’s only a compile-time concern!

    • Phillip Carter
      Phillip CarterMicrosoft logo

      Hey Pavel,

      Not likely, no. Perhaps some of the scenarios that Type Providers enable today could be fulfilled by new libraries that use Source Generators. But the way that Type Providers deeply integrate with the F# language would be unlikely to happen with C#. At least certainly not with Source Generators.

  • zig zag
    zig zag

    This is great.
    Could it made that generated code is not written as a basic string? It is code after all, but when writing string of code like in the example, I imagine there is no IntelliSense, type checking etc. Treating it as code with all IDE tooling support C# developers are used to would make it much easier to work with.

  • Avatar
    Haymo Kutschbach

    Great feature, thank you!
    And you made it very clear: no rewriting intended. However, I “+1” for a rewriting feature. Since you asked for early feedback: is there a list of concerns regarding rewriting? This would be a very valuable feature and we are ready to work around any concerns to see it come to light at some point in the future of the .NET ecosystem.

  • Avatar
    Tuomas Hietanen

    The difference between “code generation” and “compiling”: In code generation the end-result can be modified manually, creating an abstraction level mismatch, and code maintenance problem. Besides that, how do you get the syntax-errors and debugging from a StringBuilder?

    • Avatar
      Ian Marteens

      I sincerely hope it doesn’t end up as Java Annotations. Lombok, for instance, is one of the worst things that ever happened to Java. A new language, but no Intellisense and no Javadoc. Honestly, I would have preferred the dreaded macros instead of this sneaky code generation. At least, you can check easily what a macro is supossed to do.

  • Avatar
    MgSam

    I still think you guys need to take a bigger view of this feature and perhaps involve the wider VS team to reconsider whether T4 templates should remain persona-non-grata. It’s pretty clear Microsoft understands the use-case for source code generation. So why has C#/VS’s templating engine been left for dead for nearly a decade with no clear replacement?

    Authoring these source generators using strings seems like a terrible experience. Using a runtime T4 with syntax support seems like a great way to get the best of both worlds with the technology. That way you still get templating support, while also having access to Roslyn’s information about the code base.

    • Phillip Carter
      Phillip CarterMicrosoft logo

      We expect that Source Generators will obviate T4, which unfortunately does depend on the MSBuild trickery mentioned in the post. The current requirement to use strings is just the first preview. Although it is the most flexible approach, it’s also the most rudimentary. We’ll likely explore some additional approaches, such as using the SyntaxFactory APIs.

  • Avatar
    Christian

    Great! Thank you that you are coming back to this feature. I was pretty disappointed when it was dropped back then. After having played around with the preview I am also a bit on the fence regarding the apparently very firm decision to not support rewriting. I do see the problems and am also of the opinion that practicing some restraint with a feature like this can actually make it better in practice for many real world scenarios. Still I would like to offer my opinion that a constrained and more explicit rewrite-support could be a good middle ground. For example don’t allow any source generator to rewrite arbitrary code anywhere in the compilation but create explicit extension points that also force the consumer of the source generators of defining the order of their execution.

  • Yacoub Massad
    Yacoub Massad

    Once this feature is shipped, would it be supported to consume a source generator from a .NET framework project? That is, from a .NET framework project add the source generator nuget as a source generator?

    If this is the case, can this be tested now in VS preview?

    • Phillip Carter
      Phillip CarterMicrosoft logo

      Hello Yacoub,

      Source Generator components are not currently planned to be considered supported when loaded into a .NET Framework project. While it may be possible to do this with the early preview, as more aspects of this feature get implemented you may find that some things don’t work. This is in alignment with our investments being on .NET 5 (and .NET Core) moving forward.

  • Avatar
    Lior Tal

    Very cool!

    How is this different from any other code generation framework? For example – T4.

    Apart from the different syntax, we can already generate new code dynamically, why is the new approach better or stronger than what is already available today?

  • Jefferson Motta
    Jefferson Motta

    Back in time, in 1993/96. When I were using Clipper 5.x, this programing language had two pre-compiled command:
    xcommand and
    xtranslate

    This was so amazing that would be greate if C# had it too.

    I had commnads like “init screen”; “init CRUD window”; “create index [,…]”.

    Best,

    Jefferson S. Motta

    jefferson2020

    https://vivaclipper.wordpress.com/tag/xtranslate/
    https://github.com/leprechuanese/factsys/blob/master/factsys2/factsys/PLUGINS/CLIPPER.CH

  • Avatar
    Andriy Savin

    Great feature! My questions:
    1. It was mentioned that generated files are added to the project. I can imagine that can create big clutter in case there are many files generated. Imagine project with many View Models all requiring implementing INotifyPropertyChanged, each being paired with a generated part. Can this be made configurable? For example, XAML tooling produces generated files in obj directory and they are added to compilation (I understand that this is done in quite a different way), but are not included in the project.
    2. Do the generated files also become targets for Source Generators? Is it possible that a generator will get stuck in a loop generating new files for previously generated ones?
    3. Is there any safety guard against misbehaving/malicious generators which could fill my solution directory with millions of files (one example is above)?
    4. The AutoNotifyGenerator sample is great, but I see one potential problem: it’s based on defined fields, not properties (which are generated). The problem is that when you add a field to a View Model, you have to build you project before you can use intellisense when referencing properties of that View Model. Or will generators also run in background while I’m typing code?

    • Phillip Carter
      Phillip CarterMicrosoft logo

      Hey Andriy

      For (1), I’ve adjusted the blog post to be a bit less specific. The current design emits source files in memory, but this is still an early preview and so we are considering various options. Right now there’s no on-disk impact of source generation. This may be revisited, though. I imagine that some additional configuration will be required if they’re written to disk.

      For (2), not currently, no. Writing a Source Generator that depends on another Source Generator’s generated files implies an order of execution, which isn’t the case today. This may be revisited in the future.

      For (3), there are no safeguards in place for Source Generators today. You could write one that downloads a 10GB file, for example, hosing your compilation. But this is also no different than any other component that could be activated via MSBuild.

      For (4), Source Generators currently do run in the background (Visual Studio does what’s called a Design-Time Build that literally builds your code in the background). However, there are some big tooling gaps as described in the post. Eventually, we’ll make sure that things like IntelliSense work correctly and things get updated whenever a Source Generator is finished running. The current AutoNotifyGenerator is a very simple example, and not likely to be representative of a “real” one when the Source Generators feature is completed and we start encouraging the authoring of release-quality components.

  • Avatar
    Nazım Demir

    Firstly pretty good article. Is there any risk for application security. Think like this: There are some C# code on a database. Calling this code on database and executing by C# Generator. But someone can change that code on the database. Is it risk in this scenario?

  • Avatar
    Максим Ширяев

    No code rewriting?
    No AOP?
    How? Why?
    All the internal subclassing for lazy loaded navigational properties in EF just could be done using generators…
    An example with INotifyPropertyChanged is great but is requires to pre-cook the original class to be partial etc.

    • Phillip Carter
      Phillip CarterMicrosoft logo

      Hello,

      At this point we’re not considering code rewriting, which is primarily driven by what was written in the blog post: it is a goal in C# to have straightforward semantics, where the code you see tends to execute exactly as it is written. AOP tends to violate this characteristic, as does other techniques for modifying generated source at build time. This may be something we revisit in the future, but it is currently not a goal for us.

  • Avatar
    Dr. Chris of Rain

    If you want to debug the source generator, this worked for me:
    1. Open a new Visual Studio instance.
    2. Open Debug -> Attach to Process.
    3. Attach to the VBCSCompiler.exe process. (Note that this process stays alive even when you aren’t compiling.)

    I’ve only tried basic things like setting breakpoints and inspecting locals and I haven’t hit any issues so far. Though this isn’t an “official” solution, so your mileage may vary.

  • Ahmad Farazmand
    Ahmad Farazmand

    Hi.
    This is so great but i have a question.
    What about performances if we use a lot of generate scripts for each user?
    For example i want generate one of my patterns in my project for each user and detect my user behaviors and save to generate it later?

  • Diego Frata
    Diego Frata

    As a regular abuser of Fody, I think this is a great feature to have! I installed .NET Core 5 Preview 3 on macOS and I can compile the samples from Roslyn’s Github repo. However, if I take the same sample folder out of Roslyn’s tree, then I can no longer compile it. It seems to depend on having a Directory.Build.props file with an import to Microsoft.DotNet.Arcade.Sdk and also the UsingToolMicrosoftNetCompilers flag. Can you have a look and perhaps update the documentation?

      • Avatar
        声音

        After a difficult search, we got the following construction experience

        1: SourceGenerators only need to refer to Microsoft.CodeAnalysis.CSharp.Workspaces
        2: a. GeneratedDemo.csproj references the SourceGenerators project and sets OutputItemType=”Analyzer”
        b. Reference Microsoft.Net.Compilers.Toolset

        The experience is very difficult. Will the future version of visual studio 2019 improve?
        Or did I not find the best solution?

    • Phillip Carter
      Phillip CarterMicrosoft logo

      Hey Diego,

      Unfortunately, we’ve uncovered an issue with the .NET SDK where the correct C# compiler wasn’t getting packaged. The reason why this works in Visual Studio is that VS has the correct compiler. The reason why this works in the sample repo is that the build pulls in the correct compiler. But if you pull out that sample into a different directory, it will use the compiler in the .NET SDK, which is incorrect. We’ll get this fixed up in the next preview.

  • Jose Diego Menendez del Cueto
    Jose Diego Menendez del Cueto

    Amazing idea… really
    But i dont think that disallowing rewritting is an intelligent decision…
    I could say a lots of reasons like others did … for example AOP frameworks would be easy to write…
    I also understand that rewriting enables a lot of problem and i think that one of its greater problems is that with that freedom …. the anti patterns will rain…
    However there is 2 things that makes me choose to enable rewriting…
    1-) its simpler to adopt because it make codegeneration api homogeneus because there is not tricky cases, basically you can rewrite your entire project…I really think that as simple is the idea as stronger it is …
    2-)This point is very important… why to provide an api restricted when all the disadvantages of the rewritting already exists with a litle of knowledge of msbuild, roslyn and a simple console app… Actually thats all what this feature is right?….a lot of glue to stay together msbuild silent(background) build, roslyn and maybe nuget…
    I see the first proposal of this feature as part of the language on github with all the new keywords and that has a lot of tricky cases wich as i say before Are Not Welcome!!!
    I think this is the rigth aproach a compiler feature that allows generate code inside the compilation procces …its so clear that its beatyfulll…
    I am really interested on this and i will like to know if there is a place where this discussion on if allow rewritting or not can continue… or if there is not turning back

  • Avatar
    WDS_ACCOUNT®

    something around Lazarus-IDE :: Write Once, Compile Everywhere?

    so there are codes for accessing folders and files in the Operating System Structures;
    and then if compiling on Linux, Apple the path c:\users\username\desktop the compiler automatic include the file where directories path are specified?

  • Троепольский Алексей
    Троепольский Алексей

    Awesome! I do love code generation, and I often use t4.
    I have been waiting for some language feature from C# as in the Nemerle language – (If I not mistaken) there you can use the language construct to bypass for example all the fields of the class and do something without using reflection, i.e. the loop unfolds at the compilation stage. It will be useful for serialization, clone, equals etc.
    So it will be great to integrate it to the language, but this step is already a very good start.

    • Phillip Carter
      Phillip CarterMicrosoft logo

      Hello,

      We are not currently intending on integrating source generators with the language itself like how Nemerle and other languages allow. This design was explored a few years ago, but the takeaway was that it was massively complicated from a design and implementation standpoint. Scoping Source Generators to a compiler feature that acts very similar to Analyzers enables the most important scenarios while ensuring we can design and implementing something soundly by a .NET 5/C# 9 timeframe.

  • Anders Liander
    Anders Liander

    I really like that this feature is a middleware in the existing compilation pipeline. I tried it to remove reflection-based mappings and I must say that the result really gets much easier to debug while still having the friction free plumbing experience.

    Worth mentioning is that even though you cannot yet do things like goto-definition on generated in-memory-code (preview 5) you can still debug with step-into, click decompile source and continue stepping! Much better experience than I thought.

  • Avatar
    Nawfal Hassan

    Hi Philip, excellent.. Please let me know if source generators are helpful in my scenario.

    Say, I am the author of a .NET Library. Let me call my library as L. Consumer of my library is C. Let’s call Source Generator assembly as S.

    C adds L to his project as a nuget package. The purpose of L is, when C compiles his code, L inspects C’s codebase and amends it (i.e. generates additional source). I have 3 questions here:

    1. Can L be written in such a way that it inspects C’s code (using Source Generator feature of course) and amend it? In this case L would be having dependency on S, not C. Or is it C who should be adding reference to S? Basically when C calls

      L.GenerateSource();

      The GenerateSource method in L should be able inspect C’s classes. All the code generation logic itself should sit in L, not C for me.

    2. When C adds a L as a nuget package, can C have dependency only on L? Or would C need to have both dependencies, ie. L as an assembly reference and S as an analyzer?

    3. If this is a C# 9 feature, can L be compiled with C# 9, but C is on an older version of C#? Would that work?

    Best regards

  • Avatar
    circles-arrows.com

    OMG! FINALLY!!!!!

    This is great for injecting code from (xml / json) metadata files (even code like: #error Metadata file abc has problem xyz, mWahahaha)
    And an extension method generator for “default interface methods”, so we get full mix-ins with c# 9 😀

    Thank you, thank you, thank you!

  • Avatar
    Kalle Niemitalo

    On Windows, does the C# compiler ask Antimalware Scan Interface (AMSI) to scan the generated source code, like PowerShell does (SecuritySupport.cs)? Antimalware software can install a file system minifilter to scan other source files when they are read or written, but that will not work with source code that is generated by a source generator and then used by the C# compiler without ever being written to a file.

  • Avatar
    Frederic Forjan

    Did you consider this as a way to rewrite resources (resx) in .net and avoid having the C# added under source control ?
    i can see this to generate the resources.generated.cs on the fly and avoid to ‘manage’ it ?

  • Avatar
    Dr. Chris of Rain

    I ported a serializer library from a project of mine to use source generators. Here are some of my thoughts:

    1. Debugging support is desperately needed. At minimum it would be good to see the details of exceptions that crashes the source generator. But being able to easily attach a debugger would make life a lot easier.

    2. Roslyn’s diagnostic system seems to be pretty thorough. But if you are developing a library, sometimes you just want something quick and dirty. It would be good if there was a simple way to output debug logs, warnings, errors, etc.

    3. Roslyn’s API is massive. This is somewhat understandable because it is a compiler. But it can be pretty hard to find anything. For example, presumably there code somewhere that creates a mapping between the Accessibility enum and its string representations. But I couldn’t find it.

    4. I suspect that for a lot of source generator libraries, the semantic model will be the most useful. So, it is a little strange that it isn’t presented front and center in the source generator interface. I probably wouldn’t have been able to figure out how to access the semantic model without looking at the samples.

    All that being said, I think this is a pretty cool feature and I am definitively looking forward to its official release. Keep up the good work!

  • Avatar
    michael Lang

    A long time ago, when .NET 1.0 was the new kid on the block, Code Generators (not to be confused with Source Generators) were all the rage. For a long time, for many reasons, I had no interest them. I only became sold on Code Generators the day MS introduced partial classes in .NET 2.0, however just when I was finally on board, they fell out of favour. With .NET 2.0 they also introduced Entity Framework, and with that Code Generators such as MyGeneration and CodeSmith were suddenly yesterdays news. The majority of people were only generating code to talk to the database, so they saw no need for CodeSmith and MyGeneration, which essentially was replaced by in built VS scripts and T4.

    It feels like a dark secret, but I’m actually still using MyGeneration. I use it to generate all our EF classes and repositories based on database meta data and hand coded MyGeneration scripts. I use MyGeneration over T4 as it just seems a whole lot easier and more powerful.

    I think Code Generation is great for bridging application domains that are physically separated yet tightly coupled such as the example you’ve given above with a client generating code based on meta data for a web service, or generating EF code based on a database schema, or going the other way and generating SQL scripts base on EF code etc.

    Source Generators seem like something you could use to create your own scripting language like Code Smith, MyGeneration or T4… rather than a scripting language in itself. It’ll be interesting to see where Microsoft runs with this, and what it gets used for. Is Microsoft already using this internally for anything?

  • Pierre Picard
    Pierre Picard

    Hi,
    This is an interesting feature indeed, but there was another way to do the same thing. Let’s consider the C++ concept of constexpr. If there was a similar feature in C# like “compile time blocks” which would contain code executed at compile time, it would allow to do the same thing as Source Generators for most cases. I understand that it would be much more work for the team working on the C# compiler, but for an application developper it would have been much much more simple and accessible than having to: rely on Roslyn to walk along ASTs, building strings containing C# code, and create an external analyzer package.

    • Avatar
      David Lewis

      T4 templates don’t have access to your programs structure at compile time. even when running from the same assembly. Source generators do have access to that structure and are brought in as a library rather than copy pasting into your source code. since source generators allow for compile time introspection and code generation there are opportunities to do things like IOC containers with zero runtime reflection overhead and I can see things like automapper and ASP.Net being rewritten using this technology to be MUCH faster.