I love this feature. Recently I made use of it with Dapper ORM with great success. Generic type constraints allow developers to constrain initialisation of classes by their generic parameters to a particular type. So say you have the class MyClass<T> which expects you to pass in a type as a generic parameter, generic type constraints allow you to specify the class, or a derived class that is passed in. I've recently started building a media gallery (you know upload images, videos, documents etc. on the fly inside of an Angular app) to practice various coding practices and I decided to use Dapper rather than the Entity framework for data access. Dapper ORM makes use of data repositories (kinda) following the Unit of Work pattern. It's really quite marvellous! Let's start off with the abstract `DbRepositoryBase` class which will have only one instance member; an instance of `IDbConnection` named `_db`. This is the object that Dapper uses to connect to the SQL Server database:

public abstract class DbRepositoryBase
{
    protected IDbConnection _db = new SqlConnection(ConfigurationManager.ConnectionStrings["db"].ConnectionString);
}

Now we have the base db repository class setup we can inherit from it in our concrete implementation of our repository for derived instances of our abstract `Media` class, which can be found below:

public abstract class Media
{
    public int? ID { get; set; }
    public string Guid { get; set; }
    public FileType FileType { get; set; }
    public int? Size { get; set; }
    public string Caption { get; set; }
    public DateTime? DateStamp { get; set; }

    public string MediaUrl
    {
        get {
            return GetMediaUrl();
        }
    }
    public abstract int? GetMediaTypeId();
    public abstract string GetMediaUrl();
}

A concrete implementation of the `Media` class called `Image` would look something like the below:

public class Image : Media
{
    // Instance fields
    public int? Width { get; set; }
    public int? Height { get; set; }
    public int? DPI { get; set; }
    public string CameraModel { get; set; }
    public string CameraLens { get; set; }
    public string ExposureInformation { get; set; }
    public string ColourProfile { get; set; } // e.g. sRGB

    // Overridden methods
    public override string GetMediaUrl()
    {
        return string.Empty;
    }

    public override int? GetMediaTypeId()
    {
        throw new NotImplementedException();
    }
}

Now we've got the necessary models setup, we can write the `MediaRepository<T>` class where `T` is any derived class inheriting from `Media` (e.g. `Image`, `Video`, `Document` or any other format of media you can shake a stick at!). The below code presumes that all media types will share the same database table. If you need to vary the SQL statements that you use Dapper to query with, then you can use `if(obj is T)` to change the expected behaviour:

public class MediaRepository<T> : DbRepositoryBase where T : Media
{
    public T Find(int id)
    {
        string sql = "SELECT * FROM Media JOIN FileType ON Media.FileTypeId = FileType.ID WHERE ID = @id";
        return _db.Query<T>(sql, new {id = id}).FirstOrDefault();
    }
    
    public Media Find(string key)
    {
        string sql = "SELECT * FROM Media JOIN FileType ON Media.FileTypeId = FileType.ID WHERE Guid = @key";
        return _db.Query<T>(sql, new { key = key }).FirstOrDefault();
    }

    public void Add(T obj)
    {
        string sql = "INSERT INTO Media(Guid,FileTypeId,Size) VALUES(@Guid,@FileTypeId,@Size, @Caption)";

        if(obj is Image)
        {
            sql = ""; // Something specific to the Image class
        }

        _db.Execute(sql, new { Guid = obj.Guid, FileTypeId = obj.FileType.ID, Size = obj.Size, Caption = obj.Caption });
    }

    public void Update(T obj)
    {
        string sql = "UPDATE Media SET Guid = @Guid, FileTypeId = @FileTypeId, Size = @Size, Caption = @Caption WHERE ID = @id";
        _db.Execute(sql, new {Guid = obj.Guid, FileTypeId = obj.FileType.ID, Size = obj.Size, Caption = obj.Caption, id = obj.ID});
    }

    public List<T> All()
    {
        string sql = "SELECT * FROM Media";
        return _db.Query<T>(sql).ToList();
    }

    public void Remove(T obj)
    {
        string sql = "DELETE FROM Media WHERE ID = @id";
        _db.Execute(sql, new{ id = obj.ID });            
    }

    public void Remove(int id)
    {
        string sql = "DELETE FROM Media WHERE ID = @id";
        _db.Execute(sql, new { id = id }); 
    }
}

Finally in our Web API 2 controller, we can instantiate the `MediaRepository<T>` class passing in whichever class (derived from the abstract `Media` class) that we wish:

public class MediaController : ApiController
{
    private MediaRepository<Image> _repo = new MediaRepository<Image>();

    public IHttpActionResult Get()
    {
        var data = _repo.All();

        return Ok(data); // Return the query results as JSON
    }
}

Of course you could abstract this out even further, by writing an interface for the CRUD methods found in the repository class above, which would look something like the below:

public interface IAnonymousTypeRepositorizer<T> where T : class
{
    T Find(int id);
    T Find(string key);
    void Add(T obj);
    void Update(T obj);
    List<T> All();
    void Remove(T obj);
    void Remove(int id);
}

And that is it! Adam and out.