vendredi 30 juillet 2021

Creating instances of generic base class

I am working with the Dapper.FluentMap library, and trying to set up auto-registration of my mapping classes. To do that, I need to call FluentMapConfiguration.AddMap<T>(EntityBase<T>) for each of the mapping classes.

I can do it like this:

public class TypeAMap : EntityMap<TypeA> {}
public class TypeBMap : EntityMap<TypeB> {}
public class TypeCMap : EntityMap<TypeC> {}

public void Register(FluentMapConfiguration configuration)
{
  configuration.AddMap(new TypeAMap());
  configuration.AddMap(new TypeBMap());
  configuration.AddMap(new TypeCMap());
  // I have a hundred of these, you can see where I'm going...
}

Obviously a problem in the making when you forget to register a map and wonder why your data isn't loading properly. So on to some reflection to auto-register:

public void Register(FluentMapConfiguration configuration)
{
  var maps = GetType().Assembly.GetExportedTypes().Where(t =>
      !t.IsAbstract &&
      !t.IsInterface &&
      t.BaseType is { IsGenericType: true } &&
      t.BaseType.GetGenericTypeDefinition() == typeof(EntityMap<>)
    ).ToArray();

    foreach (var map in maps)
    {
      var baseType = typeof(EntityMap<>);
      var typeArguments = map.BaseType.GetGenericArguments();
      var genericType = baseType.MakeGenericType(typeArguments);
      var instance = Activator.CreateInstance(genericType);

      configuration.AddMap((dynamic) instance);
    }
}

but when it gets to the call to Activator.CreateInstance, it fails, with a MissingMethodException, Cannot create abstract class. It looks like it's trying to create an instance of EntityBase<TypeA> rather than TypeAMap, and since EntityBase<T> is an abstract class, I'm getting the error. So how can I construct my instances correctly?





Aucun commentaire:

Enregistrer un commentaire