C# 将基类列表转换为派生类

C# 将基类列表转换为派生类,c#,oop,C#,Oop,我有一个基类 public Enum TestType{ A, B } public abstract class Base{ public int ID{ get;set;} } 和派生类 public class Derived1 : Base{ public string Prop1 {get;set;} } public class Derived2 : Base{ public string Prop2 {get;set;} } 然后我有一个返

我有一个基类

 public Enum TestType{
   A,
   B
 }

public abstract class Base{
    public int ID{ get;set;}
}
和派生类

public class Derived1 : Base{
   public string Prop1 {get;set;}
}
public class Derived2 : Base{
   public string Prop2 {get;set;}
}
然后我有一个返回Base的函数

public IQueryable<Base> GetData(TestType type){
   switch(type){
      case A:
        return new IQueryable<Derived1>();
      case B:
        return new IQueryable<Derived2>();
    }

}
public IQueryable GetData(TestType){
开关(类型){
案例A:
返回新的IQueryable();
案例B:
返回新的IQueryable();
}
}
现在不幸的是,我正在使用的一个工具需要实际类型,并且不能通过传递基类型而逃脱

如何将GetData的返回结果转换为它的实际类型而不是基。我在考虑使用表达式和cast,但我想不出来

理想情况下,GetData是一个获取数据的工厂,我不希望IQueryable包含混合类列表。我不知道编译时的类型!我希望在运行时有一个从基到派生的函数,而不必检查底层类型,然后执行转换(即一组if语句)

编辑:添加了一些底层代码以提供帮助。现在我使用的控件说它在base上找不到Prop1属性(如果我传入返回IQueryable的GetData的结果集),但是如果我转换它,它就可以正常工作。问题是我不知道编译时的确切类型,我只知道其中一个类将在那里。

LINQ有一个
Cast
调用,如文档所示,该调用应该适合您

var myList=GetData().Cast()

或者,您甚至可以使用
Select
扩展方法,如下所示:

var myList=GetData.Select(data=>data as Derived1)

编辑:根据您最近的问题编辑,我建议您实现一个。创建一个工厂,该工厂将完全基于传入的枚举值返回特定的类对象。这些不同的类对象都应该实现一个特定的接口,该接口上有
GetData()
方法,该方法返回该特定派生类型的
IQueryable
。您需要为工具添加的任何逻辑也可以在该类对象上完成(也可以放在接口上,以便您的原始代码也可以调用它)

这样做可以让您的代码确定在运行时动态使用哪一个,还可以让您遵循开闭原则。如果您添加了更多的派生类型,您所需要做的就是创建一个实现接口的新类对象,确保工厂知道它存在,然后让它运行。

LINQ有一个
Cast
调用,如文档所述,该调用应该适合您

var myList=GetData().Cast()

或者,您甚至可以使用
Select
扩展方法,如下所示:

var myList=GetData.Select(data=>data as Derived1)

编辑:根据您最近的问题编辑,我建议您实现一个。创建一个工厂,该工厂将完全基于传入的枚举值返回特定的类对象。这些不同的类对象都应该实现一个特定的接口,该接口上有
GetData()
方法,该方法返回该特定派生类型的
IQueryable
。您需要为工具添加的任何逻辑也可以在该类对象上完成(也可以放在接口上,以便您的原始代码也可以调用它)


这样做可以让您的代码确定在运行时动态使用哪一个,还可以让您遵循开闭原则。如果要添加更多派生类型,只需创建一个实现接口的新类对象,确保工厂知道它存在,然后让它运行。

使用泛型并使GetData方法泛型:

public IQueryable<T> GetData<T>() where T : Base
{
    var data = ...; //object to return
    return (IQueryable<T>)data;
}
public IQueryable GetData(),其中T:Base
{
var data=…;//要返回的对象
返回(IQueryable)数据;
}

我认为这就是您最终要做的。

使用泛型并使您的GetData方法泛型:

public IQueryable<T> GetData<T>() where T : Base
{
    var data = ...; //object to return
    return (IQueryable<T>)data;
}
public IQueryable GetData(),其中T:Base
{
var data=…;//要返回的对象
返回(IQueryable)数据;
}

我想这就是你最后想要做的。

我最后做了以下几件事:

var ds = GetData(...);
if(ds.Any()){
    var m = typeof(Queryable).GetMethod("Cast",BindingFlags.Static | BindingFlags.Public, null,new[] { typeof(IQueryable<Base>) }, null).MakeGenericMethod(ds.First().GetType());
    var r = m.Invoke(ds, new[] {ds});
}
var-ds=GetData(…); if(ds.Any()){ var m=typeof(Queryable).GetMethod(“Cast”,BindingFlags.Static | BindingFlags.Public,null,new[]{typeof(IQueryable)},null).MakeGenericMethod(ds.First().GetType()); var r=m.Invoke(ds,new[]{ds}); }

有人有问题或想在这里查看问题吗?

我最后做了以下工作:

var ds = GetData(...);
if(ds.Any()){
    var m = typeof(Queryable).GetMethod("Cast",BindingFlags.Static | BindingFlags.Public, null,new[] { typeof(IQueryable<Base>) }, null).MakeGenericMethod(ds.First().GetType());
    var r = m.Invoke(ds, new[] {ds});
}
var-ds=GetData(…); if(ds.Any()){ var m=typeof(Queryable).GetMethod(“Cast”,BindingFlags.Static | BindingFlags.Public,null,new[]{typeof(IQueryable)},null).MakeGenericMethod(ds.First().GetType()); var r=m.Invoke(ds,new[]{ds}); }

有人有问题或想在这里看到问题吗?

。你怎么会期望有一个混合项目的列表?不会有混合项目items@dbarnes请您在
IQueryable GetData()
中添加一些代码,以帮助演示如何返回不同的数据类型?如果你不想要一堆If语句,我们需要看到数据如何生成的逻辑,因为类似的逻辑需要加入到转换中。好吧,我添加了一些代码,我认为你不需要实际转换就无法逃脱。你怎么会期望有一个混合项目的列表?不会有混合项目items@dbarnes请您在
IQueryable GetData()
中添加一些代码,以帮助演示如何返回不同的数据类型?如果你不想要一堆If语句,我们需要查看数据生成的逻辑,因为类似的逻辑需要进入转换。好吧,我添加了更多的代码任意数,但现在我有4个,每个IQueryable都有相同的类型,我正在考虑做一个OfType并检查null和contin