简体   繁体   中英

Complex inheritance pattern for (JSON) data contracts

I started off with a simple data model:

{
    "Make" : "Honda",
    "Model" : "Civic",
    "Engine" : {
        "Location" : "Front"
    }
}

This object satisfied my use cases, until I got an additional requirement, so it became:

{
    "Make" : "Honda",
    "Model" : "Civic",
    "FuelType" : "Gasoline",
    "Engine" : {
        "Location" : "Front",
        "MPG" : 39
    }
}

OR

{
    "Make" : "Tesla",
    "Model" : "Model S",
    "FuelType" : "Electric",
    "Engine" : {
        "Location" : "Back",
        "Range" : 300
    }
}

Now, I know that I can't override using a derived return type in C#, so the following class structure won't work:

abstract class Car { abstract Engine Engine; }

class GasolineCar : Car { override GasolineEngine Engine; }

class ElectricCar : Car { override ElectricEngine Engine; }

abstract class Engine { string Location; }

class GasolineEngine : Engine { int MPG; }

class ElectricEngine : Engine { int Cells; }

Is there a similar recommended way to model this data pattern? Requirements are:

  1. I can easily deserialize it using JSON.NET
  2. I can use the base Car & Engine types 90% of the time and only cast it when type-specific fields are needed.

Note: Please don't offer alternate solutions specifically for the above example. I know nothing about cars, and my real use case definitely needs to use this pattern or something similar.

I think you are definitely over complicating your classes. Why not simple use these classes, the json can be de-serialised to these classes easily

class Car
{
    public string Make { get; set; }
    public string Model { get; set; }
    public string FuelType { get; set; }
    public Engine Engine { get; set; }
}

class Engine
{
    public string Location { get; set; }
    public string MPG { get; set; }
    public string Range { get; set; }
}

Generally methods are these the get overridden fields cannot be overridden . So you have to override your Get - Set Methods

public abstract class Car { public virtual Engine Engine { get; set; } }

public class GasolineCar : Car {
    private GasolineEngine _engine;
    public override Engine Engine { get { return _engine; } set { this._engine = (GasolineEngine)value; } }
}

public class ElectricCar : Car
{
    private ElectricEngine _engine;
    public override Engine Engine { get { return _engine; } set { this._engine = (ElectricEngine)value; } }
}
public abstract class Engine { public string Location; }

public class GasolineEngine : Engine { int MPG; }

public class ElectricEngine : Engine { int Cells; }

Alternatively if Type restriction is what matters .

public abstract class Car<T> { public virtual T Engine { get; set; } }

public class GasolineCar : Car<GasolineEngine> {}

public class ElectricCar : Car<ElectricEngine>{}
public abstract class Engine { public string Location; }

public class GasolineEngine : Engine { int MPG; }

public class ElectricEngine : Engine { int Cells; }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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