You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.Net动态创建类型传入泛型方法报错,求可行实现方案

问题:通过动态类型调用泛型MongoDB查询方法报错

我正在开发一个可复用的小型控制台应用程序,用于从MongoDB中获取信息。我编写了一个查询数据库的方法,返回类型为IMongoQueryable<T>。由于是控制台应用,我希望通过参数传入要使用的类/类型。但在以下代码中,调用GetDetails<typeArgument>(connectionString, db, collection)时出现错误:

CS0118 'typeArgument' 是变量,但被当作类型使用

代码如下:

void Main()
{
    var connectionString = "connectionString";
    var db = "dbName";
    var collection = "CollectionName";
    var activityId = 992018;
    string typeName = "Simon.AgentActivityDetails";
    Type typeArgument = Type.GetType(typeName);
    var result = GetDetails<typeArgument>(connectionString, db, collection); //<-- 错误位置

}

public IMongoQueryable<T> GetDetails<T>(string connectionString, string db, string collection)
{
    var dbClient = new MongoClient(connectionString);
    IMongoDatabase _mongoDb = dbClient.GetDatabase(db);
    IMongoQueryable<T> result = _mongoDb.GetCollection<T>(collection).AsQueryable();
    return result;
}

请问我想要实现的功能是否可行?如果可行,该如何实现?


解决方法

功能完全可行,问题出在你试图用变量作为泛型参数——泛型参数需要编译期确定的类型,或者通过反射实现动态调用。以下是两种可行方案:

方案一:通过反射调用泛型方法

因为你是通过字符串动态获取Type对象,只能用反射来调用泛型方法:

void Main()
{
    var connectionString = "connectionString";
    var db = "dbName";
    var collection = "CollectionName";
    string typeName = "Simon.AgentActivityDetails";
    Type typeArgument = Type.GetType(typeName);
    
    // 获取泛型方法定义并生成特定类型的方法实例
    var method = typeof(YourClassName).GetMethod("GetDetails").MakeGenericMethod(typeArgument);
    // 调用方法:静态方法第一个参数传null,实例方法传当前类实例
    var result = method.Invoke(this, new object[] { connectionString, db, collection });
}

public IMongoQueryable<T> GetDetails<T>(string connectionString, string db, string collection)
{
    var dbClient = new MongoClient(connectionString);
    IMongoDatabase _mongoDb = dbClient.GetDatabase(db);
    return _mongoDb.GetCollection<T>(collection).AsQueryable();
}

注意:YourClassName需要替换为包含GetDetails方法的类名。调用后result类型为object,若需后续操作可转换为非泛型的IQueryable接口。

方案二:已知类型分支处理(无反射)

如果控制台应用的目标类型是已知的,可通过分支直接指定泛型参数,避免反射开销:

void Main(string[] args)
{
    var connectionString = "connectionString";
    var db = "dbName";
    var collection = "CollectionName";
    string typeName = args[0]; // 假设从命令行参数获取类型名
    
    switch(typeName)
    {
        case "Simon.AgentActivityDetails":
            var result = GetDetails<Simon.AgentActivityDetails>(connectionString, db, collection);
            // 处理当前类型的查询结果
            break;
        case "Another.BusinessType":
            var anotherResult = GetDetails<Another.BusinessType>(connectionString, db, collection);
            break;
        // 扩展其他已知类型分支
    }
}

public IMongoQueryable<T> GetDetails<T>(string connectionString, string db, string collection)
{
    var dbClient = new MongoClient(connectionString);
    IMongoDatabase _mongoDb = dbClient.GetDatabase(db);
    return _mongoDb.GetCollection<T>(collection).AsQueryable();
}

这种方式类型安全、性能更好,适合类型数量有限且可提前枚举的场景。

补充说明

泛型是编译期生成特定类型代码的机制,无法直接用运行期变量作为泛型参数。当类型只能在运行期确定时,反射是唯一选择,但需注意其带来的性能开销和类型安全风险。

内容的提问来源于stack exchange,提问作者Simon Price

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 03:35:25