[英]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.