【问题标题】:Pass Type to IQueryable at runtime在运行时将类型传递给 IQueryable
【发布时间】:2017-05-24 20:58:14
【问题描述】:

是否可以将类型传递给 IQueryable 以在运行时实现。

喜欢,

//Get type at runtime
Type type = Type.GetType("fully qualified class name");


IQueryable<type> test = // <-returned object of this type

实际问题如下: 下面我能够获得具有特定类型的右侧对象,但这不是转换为查询变量的类型。我也会知道查询的类型。

Dictionary<string, Type> myDictionary = new Dictionary<string, Type>()
                {
                    { "tableName", typeof(tableName) }
                };

//Below I am able to get right side object with specific type, but that is not casting to type of query variable. Also I will have known type for query.
IQueryable<Type> query= EFContext.Set(myDictionary[tableName]).AsQueryable();

稍后使用此查询对象通过动态传递 select/where 条件来选择数据。

   var data = query.Select(x=> new
                {
                    id= x.id,
                    name= x.name .. etc
                }).ToList();

后面我需要使用这个测试变量来动态查询数据。

还请提出解决此方案的任何替代方案。

【问题讨论】:

  • 不是这样的,不。您可以制作通用方法,但没有上下文就无法判断。
  • 尝试这样做表明您的程序结构存在更大的问题。您在这里的最终目标是什么?
  • 我认为可以,但是您的服务层变得非常复杂,因为您需要动态地将类型与存储库(表)进行映射。此外,处理导航属性变得非常复杂。
  • 鉴于大多数 IQueryable 扩展方法都采用特定类型的表达式,因此尝试对可查询对象执行任何操作很快就会变得非常混乱。如果您只是想要一个可查询来返回数据库中的所有实体,这是可能的,但您可能不得不使用动态结果,这同样是混乱的。你要处理多少种类型?你能用另一种方式做吗,例如围绕你想要的类型使用 switch 语句?
  • @MrZander 感谢您的回复,添加了我遇到的问题的详细信息。

标签: c# .net entity-framework linq


【解决方案1】:

如果您有需要的 IQueryable 类型示例,您可以使用泛型方法来捕获该类型 - 此方法返回正确类型的 null:

public static T NullByExample<T>(this T _) where T : class => (T)null;

如果您有返回项目的示例,您可以使用以下扩展名:

public static IEnumerable<T> EmptyByExample<T>(this T _) => Enumerable.Empty<T>();

在结果上使用AsQueryable

var test = EmptyByExample(classObject).AsQueryable();

或创建一个IQueryable 变体 - 不幸的是,实际上并没有与Enumerable.Empty 等效的IQueryable

public static IQueryable<T> EmptyQueryByExample<T>(this T _) => Enumerable.Empty<T>().AsQueryable();

var test = EmptyQueryByExample(queryObject);

否则,如前所述,您处于反思的世界,这可能表明您做错了什么。问题是你会发现在这种情况下你只能让test 成为object 类型,因为编译器不知道type 代表什么,例如var 是编译时的简写,除非你想使用 dynamic(你也不应该这样做)。

【讨论】:

    【解决方案2】:

    有一些方法可以通过反射来完成您的要求,但可维护性将受到限制。您最好为您的类型创建一个共享接口并编写一个通用方法,如下所示:

    interface IMyInterface
    {
        string SomeProperty {get;set;}
    }
    
    class MyClass : IMyInterface
    {
        public string SomeProperty {get;set;}
    }
    
    IQueryable<T> SomeMethod<T>() where T : IMyInterface, new()
    {
        var result = new List<T>() { 
            new T() { SomeProperty = "a"}, 
            new T() { SomeProperty = "b"} 
        };
        return result.AsQueryable();
    }
    

    所以对泛型方法的调用可能是:

    var temp = SomeMethod<MyClass>();
    

    【讨论】:

      猜你喜欢
      • 2013-08-13
      • 1970-01-01
      • 1970-01-01
      • 2014-05-01
      • 1970-01-01
      • 2019-12-11
      • 2011-07-28
      • 1970-01-01
      • 2021-12-16
      相关资源
      最近更新 更多