简体   繁体   English

将基列表转换为派生类

[英]Converting List of base to derived class

I have one base class 我只有一个基础班

 public Enum TestType{
   A,
   B
 }

public abstract class Base{
    public int ID{ get;set;}
}

and a derived class 和派生类

public class Derived1 : Base{
   public string Prop1 {get;set;}
}
public class Derived2 : Base{
   public string Prop2 {get;set;}
}

then I have a function that returns Base 然后我有一个返回Base的函数

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

}

Now sadly one of the tools I'm working with needs the actual type and cannot get away with passing in the base type. 现在可悲的是,我正在使用的工具之一需要实际类型,而无法传递基本类型。

How do I convert the return result from GetData to it's actual type and not Base. 如何将GetData的返回结果转换为它的实际类型而不是Base。 I was thinking using expressions and cast but I cannot figure it out. 我当时在考虑使用表达式并强制转换,但我无法弄清楚。

Idealy the GetData is a factory that get's the data, I don't expect there to be IQueryable< Base> to contain a list of mixed classes. 从概念上讲,GetData是获取数据的工厂,我不希望IQueryable <Base>包含混合类的列表。 I DO NOT KNOW THE TYPE AT COMPILE TIME! 我在编译时不知道类型! I'd like to have a function from base to derived at run time without having to check the underlying type then doing a cast( IE a bunch of if statements) 我想在运行时从基础到派生的函数,而不必检查基础类型,然后执行强制转换(即一堆if语句)

EDIT: added some underlying code to help. 编辑:添加了一些基础代码来提供帮助。 Now the control I'm using says it can't find property Prop1 on base( if I pass in the result set of GetData that returns IQueryable) but if I convert it, it works fine. 现在,我正在使用的控件说它无法在基础上找到属性Prop1(如果我传递返回IQueryable的GetData结果集),但是如果将其转换,它将可以正常工作。 the problem is I do not know the exact type at compile time I just know that one of the classes will be there. 问题是我不知道编译时的确切类型,我只知道其中一个类会在那里。

LINQ has a Cast<> call that should work for you, as documented here . LINQ有一个Cast<>调用,该调用应该对您有用,如此处所述

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

Or, you could even use the Select extension method as follows: 或者,您甚至可以使用Select扩展方法,如下所示:

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

EDIT: Based on your most recent question edit, I would recommend that you implement a Factory pattern . 编辑:根据您最近的问题编辑,我建议您实现Factory模式 Create a Factory that will return a specific class object based entirely on the enum value that gets passed in. Those different class objects should all implement a specific interface that has the GetData() method on it that returns an IQueryable of that specific derived type. 创建一个Factory,该工厂将完全基于传入的枚举值返回特定的类对象。那些不同的类对象都应实现一个特定的接口,该接口上具有GetData()方法,该方法返回该特定派生类型的IQueryable Any added logic that you'd need to do for your tool could also be done on that class object as well (and be put on the interface as well so that your original code can call it too). 您需要为工具做的任何附加逻辑也可以在该类对象上完成(也可以放在接口上,以便您的原始代码也可以调用它)。

Doing it this way allows your code to determine which one to use dynamically at run time, and also allows you to follow the Open-Closed Principle. 通过这种方式,您的代码可以确定要在运行时动态使用的代码,还可以遵循开放式封闭原则。 If you ever add more derived types, all you need to do is create a new class object that implements the interface, make sure that the Factory knows that it exists, and then just let it run. 如果要添加更多派生类型,则您需要做的就是创建一个实现该接口的新类对象,确保Factory知道其存在,然后让它运行。

Use generics and make your GetData method generic: 使用泛型并使您的GetData方法成为泛型:

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

I think this does what you are trying to do in the end. 我认为这最终将完成您想做的事情。

I ended up doing the following: 我最终做了以下工作:

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

Anyone have a problem or for see problems here? 任何人有问题或在这里看到问题?

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

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