繁体   English   中英

将基列表转换为派生类

[英]Converting List of base to derived class

我只有一个基础班

 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>();
    }

}

现在可悲的是,我正在使用的工具之一需要实际类型,而无法传递基本类型。

如何将GetData的返回结果转换为它的实际类型而不是Base。 我当时在考虑使用表达式并强制转换,但我无法弄清楚。

从概念上讲,GetData是获取数据的工厂,我不希望IQueryable <Base>包含混合类的列表。 我在编译时不知道类型! 我想在运行时从基础到派生的函数,而不必检查基础类型,然后执行强制转换(即一堆if语句)

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

LINQ有一个Cast<>调用,该调用应该对您有用,如此处所述

var myList = GetData().Cast<Derived1>();

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

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

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

通过这种方式,您的代码可以确定要在运行时动态使用的代码,还可以遵循开放式封闭原则。 如果要添加更多派生类型,则您需要做的就是创建一个实现该接口的新类对象,确保Factory知道其存在,然后让它运行。

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

public IQueryable<T> GetData<T>() where T : Base
{
    var data = ...; //object to return
    return (IQueryable<T>)data;
}

我认为这最终将完成您想做的事情。

我最终做了以下工作:

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});
}

任何人有问题或在这里看到问题?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM