Handling custom dataset in C#

I am receiving this dataset from a remote server;

TagNumber	TagCode	CageNumber	FoodType	FoodValue
A-2021-1	WHITE	A9:I10	        Milk	        A11:I
A-2021-1	WHITE	A9:I10	        Corn	        A10:I
A-2021-1	RED	A11:I13	        Meat	        B1:B2
A-2021-1	RED	A11:I13	        Hay	        A14:I
A-2021-1	GREEN	A8:J9	        Milk	        B1:B2
A-2021-1	GREEN	A8:J9	        Milk	        A10:J

I need to create this object, a complex type;

public class Animal
{
    public string TagNumber { get; set; }
    public string TagCode { get; set; }
    public string CageNumber { get; set; }
    public List<AnimalFood> Food { get; set; }
}

public class AnimalFood
{
    public string FoodType { get; set; }
    public string FoodValue { get; set; }
}

There could be many ways to handle this. This is one of them;

Create a dictionary object using LINQ GroupBy and TagCode column from incoming dataset;

var allAnimals = animalData
    .GroupBy(item => item.TagCode)
    .ToDictionary(grp => grp.Key, grp => grp.ToList());

Create unique animals out of dictionary object;

var uniqueAnimals = allAnimals.Keys.Distinct().ToList();

Create the object (animal) and add them to zoo :);

var zoo = new List<Animal>();
foreach (string animal in uniqueAnimals)
{
    var animalRow = allAnimals[animal];
    var animalRowFirst = animalRow.FirstOrDefault();
    var animalRecord = new Animal
    {
         TagNumber = animalRowFirst.TagNumber,
         TagCode = animalRowFirst.TagCode,
         CageNumber = animalRowFirst.CageNumber
    };
    //time for food
    var animalFood = new List<AnimalFood>();
    foreach(var item in animalRow)
    {
        item.Food.ForEach(x =>
        {
            animalFood.Add(new AnimalFood
            {
                  FoodType = x.FoodType,
                  FoodValue = x.FoodValue
            });
        });
    }
   //this is our custom type
   animalRecord.Food = animalFood;
   zoo.Add(animalRecord);
}

Sample output;

It’s easier to apply different filters on this object;

var animalFilter = zoo.Where(x => x.TagCode.ToUpper() == "WHITE");

Resources

https://stackoverflow.com/questions/3186818/unique-list-of-items-using-linq

Different ways to check a null object

C# provides various ways to check for a null object.

Let’s create a class to test;

public class UserObject
{
    public int Id { get; set; }
    public string? Name { get; set; }
}

The most conventional way to check for null is by equating the object with null.

UserObject userObject = null;
//Conventional way to check for null
if (userObject == null)
{
    userObject = new UserObject();
    Console.WriteLine("userObject null - handled using conventional manner");
}

if (userObject != null)
{
    Console.WriteLine("userObject not null - handled using conventional manner");
}

C#7 introduced a new way to write the above code in a more readable way by using the is keyword.

//C#7 introduces a new way 
userObject = null;
if (userObject is null)
{
    userObject = new UserObject();
    Console.WriteLine("userObject null - handled using c#7");
}

The same code can be written using null-coalescing operator.

//we can write the same code using null-coalescing operator
userObject = null;
userObject = userObject ?? new UserObject();
Console.WriteLine("userObject null - handled using null-coalescing operator");

C#9 introduced a new way to write the above code in a more readable way by using the is not keyword.

//C#9 introduces a new way 
if (userObject is not null)
{
    userObject = new UserObject();
    Console.WriteLine("userObject not null - handled using c#9");
}

Hope, this helps.

C# Design Pattern

Design pattern provides a general reusable solution for the common problems that occur in software design. The pattern typically shows relationships and interactions between classes or objects

These patterns are categorized into Structure, Creation and Behavior. This is a list of design pattern and their practical implementations.

Template Method Design Pattern

In simple words, a template method design pattern is a behavioral design pattern that defines the basic skeleton (steps) of an algorithm. In this pattern, we can change the behavior of individual steps in the derived class but can not change the sequence by which each method will be called

The real world examples are;

Making a burger

Builder Pattern

As the name suggests, this design pattern is used to build complex objects in a step by step approach. Using the same construction process we can make different representations of the object.

Suppose we have to build an object with a lot of different configurations based on a scenario. For example, we have to send an Email where we have optional properties like CC (carbon copy), BCC (blind carbon copy), attachments etc.

The real world examples are;

Sending emails

What does “where T : class, new()” mean?

Let’s start with a piece of code;

void Add<T>(T item) where T : class, new();

It’s called a ‘constraint’ on the generic parameter T. It means that T must be a reference type (a class) and that it must have a public default constructor.

That means T can’t be an int, float, double, DateTime or any other struct (value type). It could be a string, or any other custom reference type, as long as it has a default or parameter-less constructor.

For understanding we can break it into two parts;

where T : class

Means that the type T must be a reference type (not a value type).

where T : new()

Means that the type T must have a parameter-less constructor. Having this constraint will allow you to do something like T field = new T(); in your code which you wouldn’t be able to do otherwise.

We then combine the two using a comma to get:

where T : class, new()

Just to clarify, if you don’t have the class clause as part of the where T…, then it is safe to use int, float, double etc

Here is an example;

struct MyStruct { } // structs are value types

class MyClass1 { } // no constructors defined, so the class implicitly has a parameter less one

class MyClass2 // parameter less constructor explicitly defined
{
    public MyClass2() { }
}

class MyClass3 // only non-parameter less constructor defined
{
    public MyClass3(object parameter) { }
}

class MyClass4 // both parameter less & non-parameter less constructors defined
{
    public MyClass4() { }
    public MyClass4(object parameter) { }
}

interface INewable<T>
    where T : new()
{
}

interface INewableReference<T>
    where T : class, new()
{
}

class Checks
{
    INewable<int> cn1; // ALLOWED: has parameter less ctor
    INewable<string> n2; // NOT ALLOWED: no parameter less ctor
    INewable<MyStruct> n3; // ALLOWED: has parameter less ctor
    INewable<MyClass1> n4; // ALLOWED: has parameter less ctor
    INewable<MyClass2> n5; // ALLOWED: has parameter less ctor
    INewable<MyClass3> n6; // NOT ALLOWED: no parameter less ctor
    INewable<MyClass4> n7; // ALLOWED: has parameter less ctor

    INewableReference<int> nr1; // NOT ALLOWED: not a reference type
    INewableReference<string> nr2; // NOT ALLOWED: no parameter less ctor
    INewableReference<MyStruct> nr3; // NOT ALLOWED: not a reference type
    INewableReference<MyClass1> nr4; // ALLOWED: has parameter less ctor
    INewableReference<MyClass2> nr5; // ALLOWED: has parameter less ctor
    INewableReference<MyClass3> nr6; // NOT ALLOWED: no parameter less ctor
    INewableReference<MyClass4> nr7; // ALLOWED: has parameter less ctor
}

Resources

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters

https://stackoverflow.com/questions/4737970/what-does-where-t-class-new-mean

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