C#:在运行时创建泛型类型

问题描述

我有一个界面

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

作为 mongo 集合所有映射的基础。

它的实现看起来像这样

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

我正在使用扩展方法来扫描程序集并调用找到的每个映射。

就是这样。

    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 });
        });
    }

我遇到了这个问题

“System.RuntimeType”类型的对象无法转换为类型 'MongoDB.Bson.Serialization.BsonClassMap`1[Platform.Concepts.Mongo.Collections.Student]'。

此外,如果我删除了 IBsonClassMap 的 Configure 方法中的参数,并且相应地 addapt everhting,一切都会按预期进行。该方法最终被调用

所以不是这个

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

我有这个

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

解决方法

您正在将 Type 传递给需要 BsonClassMap<T> 的具体类的方法

看来你想要

object classMapInstance = Activator.CreateInstance(type.Type);

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

// create the generic instance 
object o = Activator.CreateInstance(boundedGeneric);

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

注意:完全未经测试,完全基于我的蜘蛛侠感觉