jeudi 11 mars 2021

C# : Making generic type at runtime

I have an interface

public interface IBsonClassMap<T> 
    where T : class
{
    void Configure(BsonClassMap<T> map);
}

which serves as base for all mappings for mongo collections.

An implementation of it looks like this

public class StudentClassMap : IBsonClassMap<Student>
{
    void IBsonClassMap<Student>.Configure(BsonClassMap<Student> map)
    {
    }
}

I'm using an extension method to scan an assembly and invoke each mapping found.

This is it.

    public static void ApplyConfigurationFromAssemblies(this IServiceCollection services, params Assembly[] assemblies)
    {
        Type _unboundGeneric = typeof(IBsonClassMap<>);

        List<(Type Type, Type Handler, Type Argument)> types = new List<(Type, Type, Type)>();

        foreach (Assembly assembly in assemblies)
        {
            types.AddRange(assembly
                .GetExportedTypes()
                .Where(type =>
                {
                    bool implementsType = type.GetInterfaces().Any(@interface => @interface.IsGenericType && @interface.GetGenericTypeDefinition() == _unboundGeneric);

                    return !type.IsInterface && !type.IsAbstract && implementsType;
                })
                .Select(type =>
                {
                    Type @inteface = type.GetInterfaces().SingleOrDefault(type => type.GetGenericTypeDefinition() == _unboundGeneric);
                    Type argument = @inteface.GetGenericArguments()[0];

                    return (type, @inteface, argument);
                }));
        }

        types.ForEach(type =>
        {
            object classMapInstance = Activator.CreateInstance(type.Type);

            Type unboundGeneric = typeof(BsonClassMap<>);
            Type boundedGeneric = unboundGeneric.MakeGenericType(type.Argument);

            type.Handler.GetMethod("Configure").Invoke(classMapInstance, new object[] { boundedGeneric });
        });
    }

The issue is taht I'm getting

Object of type 'System.RuntimeType' cannot be converted to type 'MongoDB.Bson.Serialization.BsonClassMap`1[Platform.Concepts.Mongo.Collections.Student]'.

Also, everything works as expected if I'm removing the argument in the Configure method of the IBsonClassMap, and addapt everhting accordingly. The method ends up getting invoked.

So instead of this

  type.Handler.GetMethod("Configure").Invoke(classMapInstance, new object[] { boundedGeneric });

I have this

   type.Handler.GetMethod("Configure").Invoke(classMapInstance, null);




Aucun commentaire:

Enregistrer un commentaire