返回从具有泛型列表的接口派生的对象

本文关键字:接口 派生 对象 列表 泛型 返回 | 更新日期: 2023-09-27 18:11:34

我的应用程序从磁盘读取JSON并使用JSON.net进行反序列化;

我的JSON是这样布局的:

{
  "driver": {
    "driverTag": "blah_blah",
    "driverName": "Blah Blah",        
    "driverTransport": "serial-device"
  },
  "devices": [
    {
      "deviceName": "Dev1",
      "deviceTag": "DEV1",
      "deviceStartMode": "Auto"         
    },
    {
      "deviceName": "Dev2",
      "deviceTag": "DEV2",
      "deviceStartMode": "Auto"          
    }
  ]
}

基于"driverTransport"的值,我反序列化为SerialDriverConfig, TelnetDriverConfig, SNMPDriverConfig…等类。

由于"driver"属性对于每个驱动程序都是相同的,无论传输类型如何,我有一个"DriverConfigTemplate"类。"设备"将因JSON文件而异,并且具有特定的传输类型属性(例如,串行设备将具有"serialPortName","serialBaudRate"等属性)

我有一个"DriverConfig"接口,其中T是"DeviceConfig"。

public interface DriverConfig<T> where T : DeviceConfig
{
    DriverConfigTemplate driver { get; set; }
    List<T> devices { get; set; }
}

设备配置如下:

public class DeviceConfig : IDeviceConfig
{
    public string deviceTag { get; set; }
    public string deviceName { get; set; }
    public string deviceStartMode { get; set; }
}

;问题部分。当我反序列化时,我事先检查传输类型并确定要使用的类;例如,对于串行驱动程序,我将使用"SerialDriverConfig"类并使用"SerialDeviceConfig"进行反序列化:

public class SerialDeviceConfig : DeviceConfig
{
    public int serialComPort { get; set; }
    public int serialBaudRate { get; set; }
    public int serialDataBits { get; set; }
    public string serialParity { get; set; }
    public string serialStopBits { get; set; }
    public string serialHandshake { get; set; }
    public int serialReadTimeout { get; set; }
    public int serialWriteTimeout { get; set; }
    public bool serialRtsEnable { get; set; }
    public bool serialDtrEnable { get; set; }
}

我的"SerialDriverConfig"类是这样的:

public class SerialDriverConfig : DriverConfig<SerialDeviceConfig>
{
    public DriverConfigTemplate driver { get; set; }
    public List<SerialDeviceConfig> devices { get; set; }
}

同样,这很好,JSON.net反序列化器完美地完成了它的工作。

我有一个函数,当JSON配置文件被加载并对其各自的模式进行验证时调用,然后传递给"DeserialiseDriverConfig"函数,我试图返回派生的驱动程序对象;这就是我卡住的地方:(

 private DriverConfig<DeviceConfig> DeserialiseDriverConfig(string _json, string _driverTransport)
    {            
        switch (_driverTransport)
        {
            case "serial-device":
                try
                {
                    SerialDriverConfig _serialDriverConfig = JsonConvert.DeserializeObject<SerialDriverConfig>(_json);
                    if (_serialDriverConfig != null)
                    {                            
                        return _serialDriverConfig;
                    }
                }
                catch (Exception e)
                {
                    //Blah blah blah
                }
                break;
        }
        return null;
    }

我已经在这个问题上困了几天了,尝试了很多东西,这就是我结束的地方。我得到"不能隐式转换类型"SerialDriverConfig"到"DriverConfig"。存在显式转换(您是否错过了强制转换?)"所以我理解为什么这个错误发生,但无法绕过它。

希望我的代码是有意义的,有人可以帮助我在这里?

返回从具有泛型列表的接口派生的对象

您可以将DriverConfig类更改为非泛型

public interface DriverConfig 
{
    DriverConfigTemplate driver { get; set; }
    List<DeviceConfig> devices { get; set; }
}

,而不是使用派生类(SerialDriverConfig等),你可以设置Json.net反序列化到正确的DeviceConfig类型基于有一个$type属性在你的JSON像这样或使用自定义的JsonConverter类似于这个

我不确定这个解决方案是否适合你的需要,但是如果你使用泛型T创建你的方法和SerialDriverConfig,你可以使用你的接口作为返回类型。你可以试试下面的代码;

方法:

private static DriverConfig<T> DeserialiseDriverConfig<T>(string _json, string _driverTransport)
{
    switch (_driverTransport)
    {
        case "serial-device":
            try
            {
                SerialDriverConfig<T> _serialDriverConfig = JsonConvert.DeserializeObject<SerialDriverConfig<T>>(_json);
                if (_serialDriverConfig != null)
                {
                    return _serialDriverConfig;
                }
            }
            catch (Exception e)
            {
                //Blah blah blah
            }
            break;
    }
    return null;
}

SerialDriverConfig类:

public class SerialDriverConfig<T> : DriverConfig<T>
{
    public DriverConfigTemplate driver { get; set; }
    public List<T> devices { get; set; }
}

你也应该考虑改变DriverConfig<T>接口方法,因为如果你让它保持原样,你会有装箱问题。如果您不需要,您可以从您的界面中删除where T : DeviceConfig或根据您当前的情况修改它。

希望这对你有帮助,如果这对你有用,请告诉我