Source generators are meant to reduce the code we write, but this might mean a generator will have a larger impact across our codebase. For example, a change to one hand-written code file could cause a source generator to cascade changes to dozens of files on every keystroke. The dramatic changes in our codebase will mean our solution needs to be reanalyzed to detect potential breaking changes.
In addition, extreme file changes may indicate a problem in the generator itself. If you ever come across this issue or find analyzing generated files unnecessary for your use case, you have an option to disable solution wide analysis for all source generated files with a new setting in the ReSharper options: Code Inspection Settings Enable solution-wide analysis Include source generated files.
Global refactorings can now be triggered from source-generated files. However, you may have noticed that source-generated code is read-only and cannot be permanently edited. Nevertheless, a simple change in the solution will trigger a source generator, undoing any changes to generated code. So why would we ever need refactorings in source-generated code?
Surprisingly, it may be beneficial to use refactorings for code generated from non-code files like CSV files, JSON, or other static assets. For example, we have a source generator attribute that takes a path to a static CSV file as input. Changing the parameter would alter the context of the previously generated code, immediately invalidating your codebase. Furthermore, such a change might introduce hundreds of compilation errors that would have to be fixed manually.
Source generators will undoubtedly change the way many .NET developers build future applications. Generating code can reduce tedious tasks, which can help reduce common copy and paste errors. While it may all feel like magic, we like to think of it more as an advanced science; a powerful tool that we should all be capable of understanding.
Using tools like ReSharper allows you to understand and interact with all parts of your applications, whether hand-written, generated, or a combination of the two approaches. With the new source generator-focused features in ReSharper 2021.2, developers will have unrivaled access to generated code and have greater solution-wide insights into their codebases. We hope you learned a few new things from this post and hope you find them helpful as you learn more about source generators.
You might find it better to create a method to include in your classes that uses reflection to copy public properties. You could save this method in resharper to regenerate into other classes you need this functionality in.
One of the most exciting features in .NET 5 and C# 9 are source generators. They enable us to hook into the compilation pipeline that is executed for our projects, analyze source files that are to be compiled, and provide additional source code for our final assembly. In other words, we can take advantage of compile-time metaprogramming!
Are you performing expensive reflection operations? Do you need to write a lot of boilerplate code like route mappings or builder methods? Source generators can make our lives a lot easier with these and many more scenarios that are yet to be discovered!
One of the crucial aspects of source generators is the IDE integration. As we write code, we should have immediate access to the code generated by source generators. For instance, when we use the Data Builder Generator by Martin Ullrich, the generated builder methods should be accessible from our project right away.
If you are not able to access MappingGenerator via the context menu (alt + enter or ctr + . ) please verify your Resharper settings related to Visual Studio Integration or Visual Studio code analysis (depends on the R# version). You can read more about proper Resharper configuration for Roslyn extensions here -with-resharper/
My most commonly used Resharper feature is its constructor parameter generator. This is useful if you are using the inversion of control principal and are using constructor injection. To use this feature, simply create a private member variable in a class:
Ugh, not you too... Come on! Invest in making the dev write *better* code instead of suggesting boiler plate goo that they won't check if it's wrong or not, resulting in crappy code that might succeed the tests but chances are these are generated by the goo generator too...
InterfaceExtractor is a code generator which extracts an interface from public members of classes and structs. This feature is really useful when you want to create static or dynamic proxies around a service or a controller for authentication or logging for example. Here is some other cool things to do with an interface. For example, this class:
Like InterfaceExtractor, PropertiesExtractor is a class generator which generates a static class to access property names in a strongly typed way. For example, this class implements INotifyPropertyChanged and does not hard code the property name with a string:
aa06259810