-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Description
[Table("Animal")]
public abstract class Animal
{
public int AnimalId { get; set; }
public string Discriminator { get { return GetType().Name; } }
}
[Table("Animal")]
public class Bird : Animal
{
public string FeatherColour { get; set; }
}
[Table("Animal")]
public class Dog : Animal
{
public string FurColour { get; set; }
}
var animals = Connection.Query<Animal>("SELECT * FROM Animal")
When doing the query above you get the exception Instances of abstract classes cannot be created. I would hope that this would return a list of animals with their values being their respective derived types.
In my case I'm using TPH inheritance so there's a field on the Animal table that specifies the derived type.
My attempts to add support for this have been unsuccessful. Before SqlMapper.cs::GetTypeDeserializer() is called if the type being passed in is an abstract class then I replace the type with the one returned in the following method:
static Type GetDerivedType(Type abstractType, IDataReader reader)
{
var discriminator = abstractType.GetProperty("Discriminator");
if (discriminator == null)
throw new InvalidOperationException("Cannot create instance of abstract class " + abstractType.FullName + ". To allow dapper to map to a derived type, add a Discriminator field that stores the name of the derived type");
return Type.GetType((string)reader["Discriminator"]);
}
However it looks like at this point the reader hasn't been opened so it fails with Invalid attempt to read when no data is present.
Any recommendations on how to proceed? If there has been an effort to implement this elsewhere, please let me know!