Multi Targeting

Beginning with Wisej 3, projects will be able to target multiple frameworks.

To add multiple targets to your Wisej application, ensure the project uses the SDK-Project format and add the following tag.

// add support for .NET Framework v4.8, and .NET 6.
<TargetFrameworks>net48;net6.0</TargetFrameworks>

net48 must always come first in the csproj file to load the Wisej designer.

Conditional Compilation

You use four preprocessor directives to control conditional compilation:

  • #if: Opens a conditional compilation, where code is compiled only if the specified symbol is defined.

  • #elif: Closes the preceding conditional compilation and opens a new conditional compilation based on if the specified symbol is defined.

  • #else: Closes the preceding conditional compilation and opens a new conditional compilation if the previous specified symbol isn't defined.

  • #endif: Closes the preceding conditional compilation.

When the C# compiler finds an #if directive, followed eventually by an #endif directive, it compiles the code between the directives only if the specified symbol is defined. Unlike C and C++, you can't assign a numeric value to a symbol. The #if statement in C# is Boolean and only tests whether the symbol has been defined or not. For example:

#if NET48
    Console.WriteLine("NET48");
#endif

Partial Classes

Multitargeting will inevitably require the use of conditional compilation and excluding certain source code files from some platforms.

In our sources we used Shared Projects and conditional property groups in the project file to compile "net48/Test.cs" only on .NET 4.8 and "net6.0/Test.cs" only on .NET 6.

If you combine this technique with partial classes you can build very flexible classes that have code that compiles on different platforms:

<!-- There is no $property that is for all versions of .NET Core -->
<!-- TrimEnd() method converts the target to "net" for .NET Framework and "net{#}." for .NET Core -->

<!-- Don't compile Startup.cs on .NET Framework -->
<PropertyGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))'=='net'">
    <Compile Remove="Startup.cs" />
</PropertyGroup>
// In /code/Test.cs
public partial class Test
{
    public string MethodForAllTargets()
    {
        return "This is .NET";
    }
}

// In /code/net48/Test.cs
public partial class Test
{
    public string MethodForOneTarget()
    {
        return "This is .NET 4.8";
    }
}

// In /code/net6.0/Test.cs
public partial class Test
{
    public string MethodForOneTarget()
    {
        return "This is .NET 6.0";
    }
}

Visual Studio will show you which targets apply for each file on a drop down at the top left.

References

Once your main project targets multiple frameworks, all the projects and the libraries it references must also provide their binaries for multiple targets.

This is all done automatically as long as the referenced projects build the binaries using the standard .NET naming convention, and libraries are added using NuGet packages that provide their binaries for multiple targets.

If you use a package only for .NET 6 or only for .NET 4.8 it will still work but you have to exclude the code in the target framework that cannot use the package.

Last updated