Tag Archives: Covariance

Configuring your models with Entity Framework

One of the tricks I’ve used for a while when setting EF up in a project, is to use inheritance in order to share code, but not objects, across the business and data layers of the application.

Let’s take the following example, as shown above:

namespace MyProject.Models
{
    public class ResourceModel
    {

And now the data layer:

namespace MyProject.Data.Resources
{
    public class ResourceEntity : ResourceModel

This gives us a number of advantages: the code is shared between the objects, but the two objects are not the same. However, until recently, this presented an issue. Imagine that we had a property in the model that looked like this:

public TagModel[] Tags { get; } 

TagModel itself might have a similar inheritance structure; however, how would you return that from the data layer – since the inheritance would force it to return the same type.

Covariance return type

Fortunately, since C# 9 you can return covariants (Covariance is basically the idea that you can substitute a sub-type for a class).

What this means is that you can override the relevant property in the sub class (the data layer). First, you’ll need to make the property virtual:

    public class ResourceModel
    {
        public virtual TagModel[] Tags { get; } 
    }

And then just override it:

    public class ResourceEntity : ResourceModel
    {
        public int Id { get; set; }

        public override TagEntity[] Tags { get; }
    }

You can’t use anything like a List here, because (for example) a List of TagEntity has no relationship to a List of TagModel.

Hope this helps.

References

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/covariant-returns?WT.mc_id=DT-MVP-5004601

https://github.com/dotnet/csharplang/issues/49

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/override?WT.mc_id=DT-MVP-5004601

Casting a C# Object From its Parent

Have you ever tried to do something akin to the following:

[Fact]
public void ConvertClassToSubClass_Converts()
{
    // Arrange
    var parentClass = new SimpleTestClass();
    parentClass.Property1 = "test";
 
    // Act
    var childClass = parentClass as SimpleTestSubClass;
 
    // Assert
    Assert.Equal("test", childClass.Property1);
}

This is a simple Xunit (failing) test. The reason is fails is because you (or I) am trying to cast a general type to a specific, and C# is complaining that this may not be possible; consequently, you will get null (or for a hard cast, you’ll get an InvalidCastException.

Okay, that makes sense. After all, parentClass could actually be a SimpleTestSubClass2 and, as a result, C# is being safe because there’s (presumably – I don’t work for MS) too many possibilities for edge cases.

This is, however, a solvable problem; there are a few ways to do it, but you can simply use reflection:

public TNewClass CastAsClass<TNewClass>() where TNewClass : class
{
 
    var newObject = Activator.CreateInstance<TNewClass>();
    var newProps = typeof(TNewClass).GetProperties();
 
    foreach (var prop in newProps)
    {
        if (!prop.CanWrite) continue;
 
        var existingPropertyInfo = typeof(TExistingClass).GetProperty(prop.Name);
        if (existingPropertyInfo == null || !existingPropertyInfo.CanRead) continue;
        var value = existingPropertyInfo.GetValue(_existingClass);
        
        prop.SetValue(newObject, value, null);
    }
 
    return newObject;
}

This code will effectively transfer any class over to any other class.

If you’d rather use an existing library, you can always use this one. It’s also Open Source on Git Hib.