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

使用System.Linq.Dynamic动态查询,如何将结果转为IEnumerable?

Fixing the IQueryable to IEnumerable Conversion & Generic PagedResponse Issue

Got it, let's walk through your problem and fix it step by step. You're hitting two key roadblocks here:

  1. Converting the non-generic IQueryable (returned from DbSet.Set(Type)) to a generic IEnumerable<T> that your PagedResponse expects.
  2. Using a runtime Type variable as a compile-time generic type parameter (since returnType is a Type instance, you can't directly write PagedResponse<returnType>).

Let's cover two practical solutions—one using reflection (for when you can't modify your entity classes) and a cleaner, type-safe approach (if you can add a shared interface/base class to your entities).


Solution 1: Use Reflection to Handle Dynamic Types

This works if you can't adjust your existing entity classes. We'll use reflection to convert the non-generic query result to IEnumerable<T> and instantiate the generic PagedResponse at runtime.

Here's the revised code:

Type returnType = null;
switch (kwdType.ToLower()) 
{
    case "class1": 
        returnType = typeof(TblClass1); 
        break;
    case "class2": 
        returnType = typeof(TblClass2); 
        break;
    case "class3": 
        returnType = typeof(TblClass3); 
        break;
    default:
        // Handle invalid keyword type (throw error or return empty result)
        throw new ArgumentException("Invalid kwdType value", nameof(kwdType));
}

// Get the non-generic query result
var query = MYDB.Set(returnType).AsQueryable().Where("Active=@0", "Y");

// Convert non-generic IQueryable to IEnumerable<T> using reflection
var castMethod = typeof(Enumerable).GetMethod(nameof(Enumerable.Cast))
                                  .MakeGenericMethod(returnType);
var enumerableResult = castMethod.Invoke(null, new object[] { query }) as IEnumerable;

// Create the generic PagedResponse<T> instance at runtime
var pagedResponseType = typeof(PagedResponse<>).MakeGenericType(returnType);
var pagedResponse = Activator.CreateInstance(pagedResponseType, enumerableResult, pageIndex, pageSize);

// Return the result (adjust your method's return type to object or a shared base type if needed)
return pagedResponse;

Why this works:

  • Enumerable.Cast<T> is invoked via reflection to turn the non-generic IQueryable into a type-specific IEnumerable<T>.
  • Activator.CreateInstance builds the PagedResponse<T> instance using your runtime returnType as the generic parameter.

Solution 2: Type-Safe Approach with Shared Interface/Base Class

If you can modify your entity classes, this is the better option—it avoids reflection entirely and keeps your code type-safe.

First, define a shared interface (or base class) that all your TblClass entities implement:

public interface IActiveEntity
{
    string Active { get; set; }
}

// Update each entity class to implement the interface
public class TblClass1 : IActiveEntity
{
    public string Active { get; set; }
    // Other entity properties...
}

public class TblClass2 : IActiveEntity
{
    public string Active { get; set; }
    // Other entity properties...
}

Then rewrite your logic to use generic methods:

IEnumerable<IActiveEntity> activeEntities;

switch (kwdType.ToLower()) 
{
    case "class1": 
        activeEntities = GetActiveEntities<TblClass1>();
        break;
    case "class2": 
        activeEntities = GetActiveEntities<TblClass2>();
        break;
    case "class3": 
        activeEntities = GetActiveEntities<TblClass3>();
        break;
    default:
        throw new ArgumentException("Invalid kwdType value", nameof(kwdType));
}

// Now you can directly create the PagedResponse with the shared interface
return new PagedResponse<IActiveEntity>(activeEntities, pageIndex, pageSize);

// Helper generic method to reuse query logic
private IEnumerable<T> GetActiveEntities<T>() where T : class, IActiveEntity
{
    return MYDB.Set<T>().Where(x => x.Active == "Y");
}

Why this works:

  • All entities share the IActiveEntity interface, so we can return a common IEnumerable<IActiveEntity> from each switch case.
  • No reflection is needed—everything is validated at compile time, reducing runtime errors and making your code easier to maintain.

内容的提问来源于stack exchange,提问作者Rajeev Menon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:05:51