C#将List <baseclass>转换为List <derivedclass>

时间:2018-01-20 04:37:21

标签: c# asp.net-web-api

感谢您的帮助。我一直在努力解决这个问题太久了。

我可以通过创建两个具有重复属性列表的独立模型类来轻松解决这个问题,但我想学习如何使用基类实现此目的。因此,IntSensorExtSensor都是Sensor。从另一个类我解析一个包含所有数据的json文件,效果很好。但是,尝试调用一个返回List<Sensor>基类并尝试将其作为子类强制转换的方法正在扼杀我。我做错了什么......还是有更好的方法?谢谢!

PS:这可能看起来像一个重复的问题,但我尝试了其他解决方案,它们在“Repository类”中标记为“//在其他StackOverflow帖子中看到 - 在代码中失败”。

//模型类

public class Device
{
    public string IP { get; set; }   
    public string Name { get; set; }
    public IList<IntSensor> InternalSensors { get; set; }
    public IList<ExtSensor> ExternalSensors { get; set; }
}

public class Sensor
{
    public string Name { get; set; }
    public string ActualTemp { get; set; }
    public string HighTemp { get; set; }
    public string LowTemp { get; set; }
}

public class IntSensor : Sensor {}
public class ExtSensor : Sensor {}

// Business Class - 解析json

public class ParseJsonData
{
    public static RoomAlertModel GetRoomAlertModel(JObject jsonTree)
    {
        RoomAlertModel model = new RoomAlertModel();
        model.IP = jsonTree["ip"].ToString();
        model.Name = jsonTree["name"].ToString();

        return model;
    }

    public static List<Sensor> GetSensors(JToken jToken)
    {
        var sensors = new List<Sensor>();

        try
        {
            foreach (var item in jToken)
            {
                var s = new Sensor();
                s.Label = item["lab"].ToString();
                s.ActualTemp = item["tf"] != null ? item["tf"].ToString() : "";
                s.HighTemp = item["hf"] != null ? item["hf"].ToString() : "";
                s.LowTemp = item["lf"] != null ? item["lf"].ToString() : "";

                sensors.Add(s);
            }
        }
        catch (Exception)
        {
        }            

        return sensors;
    }
}

//存储库

public class RoomAlertRepository
    {
        internal RoomAlertModel Retreive()
        {
            var filePath = HostingEnvironment.MapPath(@"~/App_Data/RoomAlertsData.json");

            var json = File.ReadAllText(filePath);

            JObject jsonTree = JObject.Parse(json);
            var internalSensorTree = jsonTree["internal_sen"];
            var externalSensorTree = jsonTree["sensor"];

            var model = ParseJsonData.GetRoomAlertModel(jsonTree);

            var baseList = ParseJsonData.GetSensors(internalSensorTree);

            //seen on other StackOverflow Posts -- fails
            var iSensorsTry1 = baseList.Cast<IntSensor>();
            //seen on other StackOverflow Posts -- fails
            var iSensorsTry2 = baseList.ConvertAll(instance => (IntSensor)instance);
            //seen on other StackOverflow Posts -- fails
            var iSensorsTry3 = baseList.OfType<IntSensor>();

            model.InternalSensor = iSensorsTry1.ToList();


            return model;
        }
    }

1 个答案:

答案 0 :(得分:1)

GetSensors方法中,您正在创建基类Sensor的实例。试图将它们隐式地转换为其他派生类是不可能的。您应该在该方法中使用泛型类型参数,并创建实际派生类型的实例。

像这样:(注意where子句和new参数的T约束

public static List<T> GetSensors<T>(JToken jToken) where T : Sensor, new()
{
    var sensors = new List<T>();

    try
    {
        foreach (var item in jToken)
        {
            var s = new T();
            s.Label = item["lab"].ToString();
            s.ActualTemp = item["tf"] != null ? item["tf"].ToString() : "";
            s.HighTemp = item["hf"] != null ? item["hf"].ToString() : "";
            s.LowTemp = item["lf"] != null ? item["lf"].ToString() : "";

            sensors.Add(s);
        }
    }
    catch (Exception)
    {
    }            

    return sensors;
}

现在这样称呼:

List<IntSensor> iSensors = ParseJsonData.GetSensors<IntSensor>(internalSensorTree);