如何向方法/函数调用传递类型?简化泛型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
相关产品推荐
相关产品推荐

