Search code examples
c#.netdapperwebapi

How to register the class that implement interface to Dapper?


I have Dapper models that I use with ColumnAttributeTypeMapper code.

This attribute helps to map between SQL column names to the properties on the model.

One thing though, is I need to tell Dapper to know about this Model class so I need to do this code for each model:

Dapper.SqlMapper.SetTypeMap(typeof(FooModel), new ColumnAttributeTypeMapper<FooModel>());
...

I try to automate this by creating IModel interface:

public interface IModel {}

And using extenstion to find all class that implements IModel and map them:

public static class WebApplicationExtensions
{
    public static void MapModels(this WebApplication app)
    {
        var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            
        var classes = assemblies.Distinct().SelectMany(x => x.GetTypes())
            .Where(x => typeof(IModel).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract);

        foreach (var classe in classes)
        {
            Dapper.SqlMapper.SetTypeMap(classe, new ColumnAttributeTypeMapper<classe>());
        }
    }
}

app.MapModels();

But the build throw error: 'classe' is a variable but is used like a type.

I also try to do the following:

  Dapper.SqlMapper.SetTypeMap(typeof(classe), new ColumnAttributeTypeMapper<classe>());
  Dapper.SqlMapper.SetTypeMap(typeof(classe), new ColumnAttributeTypeMapper<typeof(classe)>());

But it did not work either. How to make dotnet to "register" those models to Dapper?


Solution

  • Use Type.MakeGenericType like this:

    foreach (var classe in classes)
    {
        Dapper.SqlMapper.SetTypeMap(classe, (ITypeMap?)Activator.CreateInstance(typeof(ColumnAttributeTypeMapper<>).MakeGenericType(classe)));
    }