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

如何向方法/函数调用传递类型?简化泛型Query调用代码

简化targetUnitOfWork.Query<T>的类型判断代码

我明白你想摆脱重复的类型判断逻辑,让根据动态类型调用Query<T>的代码更简洁。针对你提到的SomeListItem和SomeList两种类型,这里有几个实用的方案:

方案一:封装泛型方法(推荐,易维护)

先把针对不同类型的查询逻辑封装到一个泛型方法里,避免重复的if-else判断:

// 假设你的工作单元接口是IUnitOfWork
public T GetMatchingEntity<T>(IUnitOfWork targetUnitOfWork, object otherObj) where T : class
{
    var entityType = typeof(T);
    
    if (entityType == typeof(SomeListItem))
    {
        return targetUnitOfWork.Query<SomeListItem>()
            .Where(i => i.Name.Equals(otherObj.Name))
            .Where(i => i.SortKey == otherObj.SortKey) // 补全你的条件
            .FirstOrDefault() as T;
    }
    else if (entityType == typeof(SomeList))
    {
        return targetUnitOfWork.Query<SomeList>()
            .Where(l => l.Name.Equals(otherObj.Name))
            // 这里添加SomeList对应的查询条件
            .FirstOrDefault() as T;
    }
    
    throw new ArgumentException($"不支持的类型: {entityType.FullName}");
}

接下来,你可以根据动态类型直接调用这个泛型方法,甚至用反射进一步简化调用逻辑:

Type targetType = targetClassInfo.ClassType;
object target = null;

// 方式1:简化的if判断调用
if (targetType == typeof(SomeListItem))
{
    target = GetMatchingEntity<SomeListItem>(targetUnitOfWork, otherObj);
}
else if (targetType == typeof(SomeList))
{
    target = GetMatchingEntity<SomeList>(targetUnitOfWork, otherObj);
}

// 方式2:用反射彻底消除if判断
var genericMethod = typeof(YourCurrentClass)
    .GetMethod(nameof(GetMatchingEntity))
    .MakeGenericMethod(targetType);
target = genericMethod.Invoke(this, new object[] { targetUnitOfWork, otherObj });

方案二:反射动态构建查询(适合更复杂的动态场景)

如果你的类型较多,或者需要更灵活的动态查询,可以直接通过反射调用Query<T>并构建Where条件(前提是不同类型有统一的查询属性,比如Name、SortKey):

Type targetType = targetClassInfo.ClassType;
object target = null;

// 1. 调用Query<T>获取IQueryable
var queryMethod = typeof(IUnitOfWork)
    .GetMethod(nameof(IUnitOfWork.Query))
    .MakeGenericMethod(targetType);
var queryable = (IQueryable)queryMethod.Invoke(targetUnitOfWork, null);

// 2. 构建Name匹配的条件表达式
var parameterExpr = Expression.Parameter(targetType, "x");
var nameProperty = targetType.GetProperty(nameof(SomeListItem.Name));
var otherObjName = otherObj.GetType().GetProperty(nameof(otherObj.Name)).GetValue(otherObj);
var nameEqualsExpr = Expression.Equal(
    Expression.Property(parameterExpr, nameProperty),
    Expression.Constant(otherObjName)
);
var nameWhereLambda = Expression.Lambda(nameEqualsExpr, parameterExpr);

// 3. 调用Where方法
var whereMethod = typeof(Queryable)
    .GetMethods()
    .First(m => m.Name == "Where" && m.GetParameters().Length == 2)
    .MakeGenericMethod(targetType);
queryable = (IQueryable)whereMethod.Invoke(null, new object[] { queryable, nameWhereLambda });

// 4. 同理构建SortKey匹配的条件(如果SomeList也有SortKey属性)
if (targetType.GetProperty(nameof(SomeListItem.SortKey)) != null)
{
    var sortKeyProperty = targetType.GetProperty(nameof(SomeListItem.SortKey));
    var otherObjSortKey = otherObj.GetType().GetProperty(nameof(otherObj.SortKey)).GetValue(otherObj);
    var sortKeyEqualsExpr = Expression.Equal(
        Expression.Property(parameterExpr, sortKeyProperty),
        Expression.Constant(otherObjSortKey)
    );
    var sortKeyWhereLambda = Expression.Lambda(sortKeyEqualsExpr, parameterExpr);
    queryable = (IQueryable)whereMethod.Invoke(null, new object[] { queryable, sortKeyWhereLambda });
}

// 5. 获取最终结果
var firstOrDefaultMethod = typeof(Queryable)
    .GetMethod(nameof(Queryable.FirstOrDefault))
    .MakeGenericMethod(targetType);
target = firstOrDefaultMethod.Invoke(null, new object[] { queryable });

方案对比

  • 方案一:代码可读性高,调试方便,适合类型数量不多的场景,是最推荐的方式。
  • 方案二:灵活性强,无需提前写死类型判断,但代码复杂度高,维护成本也更高,适合类型较多或需要高度动态的场景。

内容的提问来源于stack exchange,提问作者Novice Student

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:08:22