Sharing libraries between .Net Core and .Net Framework applications

I was trying to reference a DLL targeting FW 4.6 in a host application targeting .NET Core 2.1. I started getting this error;

This is where I started to wonder, What’s the difference? How they can co-exist? How the host application can use them?

Microsoft recommend to target .NET Standard 2.0 when building reusable libraries, unless you need to support an earlier version. Most general-purpose libraries should not need APIs outside of .NET Standard 2.0. .NET Standard 2.0 is supported by all modern platforms and is the recommended way to support multiple platforms with one target.

.NET Core 2.1 and later versions support .NET Standard 2.0 and earlier versions.

There will be no new .NET Standard versions after 2.1. For more information, see .NET 5 and .NET Standard later in this article.

.NET Standard libraries and Visual Studio
In order to build .NET Standard libraries in Visual Studio, make sure you have Visual Studio 2019 or Visual Studio 2017 version 15.3 or later installed on Windows, or Visual Studio for Mac version 7.1 or later installed on macOS.

Start from here

Read about .NET standard here

A good explanation about libraries

Resources

Visual Studio licensing and pricing

There are two models. Subscription based and Volume licensing program; The subscription-based pricing is on Microsoft web site;

https://visualstudio.microsoft.com/vs/pricing/?tab=business

Professional = $45 per month

Enterprise = $250 per month

Microsoft has partners that might be able to help you in lowering subscription pricing by applying discounts that are not available to general public. In one instance I have been offered Enterprise edition @2,500/year for 5 developers.

Estimated pricing for volume licensing program (5 developers);

This program has one-time payment. This is a perpetual license and if software assurance is involved, you are eligible to get newer version. MSDN subscriptions are usually valid for two years. MSDN renewal is a recurring expense and cost about 20-30% of software cost.

Here is the breakdown;

Professional

The minimum limit here is 5 because there is no MSDN subscription.

Microsoft Visual Studio 2019 Professional – License – 1 User – Microsoft Open License – Single Language – PC

$496.57 x 5 = $2,482.85

Professional with MSDN

Microsoft Visual Studio Professional Edition with MSDN – License & Software Assurance – 1 User – Microsoft Qualified – Microsoft Open Business – All Languages – PC

$1,080.87 x 5 = $5,404.35

Enterprise with MSDN

Microsoft Visual Studio Enterprise With MSDN – License & Software Assurance – 1 User – Volume, Microsoft Qualified – All Languages – PC

$8,638.64 x 5 = 43,193.20

If budget is a constraint and wanted software assurance then I will suggest to go for Professional with MSDN. You can pick whatever suits you.

There are 3rd party vendors offer lower rates but not sure how that will work out. Here is one.

Resource

https://visualstudio.microsoft.com/vs/pricing-details/

https://docs.microsoft.com/en-us/visualstudio/subscriptions/volume-license

Install and configure Git for windows

Download Git from here;

https://git-scm.com/download/win

This is required if you want to use git from command prompt. A reboot is required after installation.

Visual Studio 2019 Settings

This is required to integrate with Azure Devops.

Tools -> Get Tools and Features -> Individual components

Search “git”. Select “Git for Windows” from menu;

Visual studio will take some time to reconfigure.

Visual Studio 2017 Settings

Open Visual Studio, Check the Git for Windows in the Tools – Get Tools and Features…), go to “Individual Item” tab,  check “Git for Windows”, and click “Modify”. Then it will ask you to update Visual Studio to the latest version, for example 15.9.36.

Click ok to install and close.

Reflection – What are the benefits

Generally, when people talk about reflection, the main concern is the performance. Because it runs on runtime, so theoretically, it is a little bit slower than the normal application. But it is flexible for many scenarios, especially if you develop the framework. If it is acceptable to spend a few seconds (or only hundreds of milliseconds) to load assemblies, then feel free to use it.

Let’s walk through an example; We are going to use an interface called “ISpeaker”.

internal interface ISpeaker
{
    string SayHello();
}

Create three implementation classes:

English Speakers

internal class EnglishSpeaker : ISpeaker
{
    public string Name => this.GetType().ToString();
    public string SayHello()
    {
        return "Hello!";
    }
}

Urdu Speakers

internal class UrduSpeaker : ISpeaker
{
    public string Name => this.GetType().ToString();
    public string SayHello()
    {
        return "as-salaam-alaikum";
    }
}

Chinese Speakers

internal class ChineseSpeaker : ISpeaker
{
    public string Name => this.GetType().ToString();
    public string SayHello()
    {
        return "Nihao";
    }
}

Now we can use reflection to find all the implementations of ISpeaker interface and call their methods or properties.

internal class ReflectionHelper
{
    public static List<Type> GetAvailableSpeakers()
    {
        // You can also use AppDomain.CurrentDomain.GetAssemblies() to load all assemblies in the current domain.
        // Get the specified assembly.
        var assembly =
                Assembly.LoadFrom(Path.Combine(Directory.GetCurrentDirectory(), "ReflectionDemo.dll"));
        // Find all the types in the assembly.
        var types = assembly.GetTypes();
        // Apply the filter to find the implementations of ISayHello interface.
        var result = types.Where(x => x.IsClass && typeof(ISpeaker).IsAssignableFrom(x)).ToList();
        // Or you can use types.Where(x => x.IsClass && x.GetInterfaces().Contains(typeof(ISpeaker))).ToList();
        return result;
    }
}

In this class, we load the specified dll file that contains types we need. Then we can apply the LINQ query to find all the implementations of ISpeaker interface using Reflection.

Test the program output. we can output the name and call SayHello method of each speaker:

using ReflectionDemo;
using System.Reflection;

Console.WriteLine("Hello, World!");

Console.WriteLine("Here is the Reflection sample:");
// Find all the speakers in the current domain
var availableSpeakers = ReflectionHelper.GetAvailableSpeakers();
foreach (var availableSpeaker in availableSpeakers)
{
    // Create the instance of the type
    var speaker = Activator.CreateInstance(availableSpeaker);
    // Get the property info of the given property name
    PropertyInfo namePropertyInfo = availableSpeaker.GetProperty("Name");
    // Then you can get the value of the property
    var name = namePropertyInfo?.GetValue(speaker)?.ToString();
    Console.WriteLine($"I am {name}");
    // Invoke the method of the instance
    Console.WriteLine(availableSpeaker.InvokeMember("SayHello", BindingFlags.InvokeMethod, null, speaker, null));
}
Console.WriteLine();
Console.ReadKey();

Run the program, you will see the below output:

If we need to add other speakers in other languages, just add the implementation classes in the same project. .NET reflection can automatically find out all the required classes and call the methods correctly.

It is extremely useful when we create the plugin-type applications. First we make the interfaces and call the methods from the client by reflection. Then we can create plugins following the interface for the client, which can be loaded as the *.dll files dynamically and executed.

Another scenario is for the framework development. As a framework developer, you will not be able to know what implementations the users will create, so you can only use reflection to create these instances. One example is in some MVVM frameworks, if you create the classes following the conventions, eg. xxxViewModel, the framework can find all the ViewModels and load them automatically using reflection.

The main namespaces we need to use for reflection are System.Reflection and System.Type. You may also need to know the below terms:

Resources

Reflection in .NET

Viewing Type Information

Dynamically Loading and Using Types

https://levelup.gitconnected.com/four-ways-to-generate-code-in-c-including-source-generators-in-net-5-9e6817db425

https://docs.microsoft.com/en-us/dotnet/core/tutorials/creating-app-with-plugin-support