Hidden features of OmniSharp and C# extension for VS Code

OmniSharp powers intellisense and language services in C# plugins and extensions for numerous editors, including VS Code. When we build things into OmniSharp, we typically try to keep things lightweight (of course if the term “lightweight” applies to anything related to MSBuild…) and non-invasive. This means that many features/tweaks are actually opt-in by default, and wouldn’t normally show up on their own.

In this post I wanted to show you a few of such less known features.

Enforcing C# EditorConfig formatting conventions at build time

EditorConfig is an excellent way to enforce stylistic rules on your C# projects. However, the rules and their corresponding IDExxxx diagnostics are only enforced in the editor, such as Visual Studio or VS Code with OmniSharp, but not at build time.

While there are various categories of EditorConfig conventions that you can use, in this post, I will show you how to enforce the formatting conventions (IDE0055) at build time.

Creating Common Intermediate Language projects with .NET SDK

When you compile your C#, F# or VB.NET code, which are all high-level managed languages, the relevant compiler doesn’t compile it to native code, but instead it compiles it into the Common Intermedia Language.

The IL code is then just-in-time (not always, but let’s keep things simple) compiled by the CLR/CoreCLR to machine code that can be run on the CPU. What I wanted to show you today, is that with the new Microsoft.NET.Sdk.IL project SDK, it is actually quite easy to create and build projects in pure IL.

Let’s have a look.

Runtime Host Configuration Options and AppContext data in .NET Core

One of the little known and rarely used hidden features of .NET Core is the ability to seed AppContext data dictionary directly from the csproj project file. This provides an interesting mechanism for exposing low-level tweaks/knobs/settings for your application code.

Let’s have a look.

Using async disposable and async enumerable in frameworks older than .NET Core 3.0

One of the awesome features introduced in .NET Core 3.0 and C# 8.0 are async streams. The feature consists of two parts - async disposable, for async clean up, as well as async enumerable, for async iteration.

Normally, the C# language features are backwards compatible and can be used regardless of the runtime framework being targeted. In this particular case, however, the newly introduced types that are needed for async streams feature to work, such as for example IAsyncDisposable or IAsyncEnumerator, were only added in .NET Core 3.0, restricting the usage of the features to that runtime, and later.

Let’s have a look at how you can still benefit from async disposable and async enumerable on older frameworks.

Instantiating an object without using its constructor in C#

In this blog post we will look at how you could create an instance of an object in C# without calling its constructor - which sounds a bit crazy, but is actually something that has been supported by both CLR and Core CLR for a long time now.

More after the jump.

dotnet-script 0.50 is out – with support for .NET Core 3.0!

We have some exciting news to announce - dotnet-script is now supporting .NET Core 3.0.

We released the new version 0.50.0, with .NET Core 3.0 support already on September 25th, two days after .NET Core 3.0 went RTM, but kept quiet about it. The reason was that a large part of the scripting experience is the tooling in OmniSharp and the C# Extension for VS Code, and that had to be updated accordingly too.

“Implementing” a non-public interface in .NET Core with DispatchProxy

Reflection is a tremendously powerful concept in .NET, which every C# developer, sooner or later, ends up working with. It is very useful for a lot of perfectly honest scenarios such as for example assembly scanning, type discovery or all kinds of application composability features.

However, it can also be used to circumvent the public API surface of the dependencies you consume - to modify them or gain access to things that the author of your dependency didn’t exactly envision. That said, this process of “hacking around” is very typical for C# development world and, albeit somewhat risky, it sometimes might be the only way out of a coding jam you are in.

Things start to get interesting if you are forced to implement a non-public (for example internal) interface. At that point, the “basic” reflection can’t help anymore, so let’s have a look at how we can do it.

Dynamic controller routing in ASP.NET Core 3.0

One of the great extensibility points in the routing feature of the older versions of the ASP.NET MVC and ASP.NET Core MVC frameworks was the ability to pick up any route and dynamically point it at a given controller/action.

This had a lot of excellent use cases - as we will briefly see - and since ASP.NET Core 3.0 Preview 7, the feature is actually finally available in ASP.NET Core 3.0 (despite not being mentioned in the official release blog post).

So, let’s have a look at dynamic routing in ASP.NET Core 3.0 together!

EditorConfig support in OmniSharp and C# extension VS Code

Recently, I blogged about Roslyn analyzers support in OmniSharp and C# extension VS Code and some background on how that feature came together.

Today I am pleased to announce that in the latest OmniSharp release - 1.33.0, where we have shipped another large feature (in fact, the 2nd most requested feature in OmniSharp repo, after, well, analyzers) and that is support for EditorConfig.

Between then, and the time it took me to finally write this post, we actually have 1.34.0 which is even better - and is in fact included in the corresponding release 1.21.0 of the C# extension for VS Code.

More after the jump.

About


Hi! I'm Filip W., a software architect from Zürich 🇨🇭. I like Toronto Maple Leafs 🇨🇦, Rancid and quantum computing. Oh, and I love the Lowlands 🏴󠁧󠁢󠁳󠁣󠁴󠁿.

You can find me on Github, on Mastodon and on Bluesky.

My Introduction to Quantum Computing with Q# and QDK book
Microsoft MVP