2

I am trying to find a way to cast a class to its superclass and still use the methods and properties that the class exposes. Check the below code;

public class Car
{        
}

public class Audi : Car
{
    private int _Mileage;
    public int Mileage
    {
        get { return _Mileage; }
        set { _Mileage = value;}
    }
}

public class BMW : Car
{
    private int _Mileage;
    public int Mileage
    {
        get { return _Mileage; }
        set { _Mileage = value;}
    }
}

public class Program
{
    //outside this class either a BMW class or Audi class is instantiated
    Audi _newCar = new Audi();

    // I don't know which one it is so I use a generic type
    Car MyCar;

    int Mileage;

    Program()
    {
        // Now I cast the unknown class to the car type
        MyCar = _newCar;

        // Although I know both Audi & BMW have the Mileage property, I cannot use it
        Mileage = MyCar.Mileage;
    }
}

The Car, Audi, BMW classes are part of the framework and I cannot change those. This framework either returns a Audi or BMW (or one of the many others).

To get the Mileage I do not want to create the exact same method for all the possible brands. However when I cast it to its superclass, I do not have access to the Mileage property anymore...

How should I be tackling this?

Bastiaan
  • 686
  • 1
  • 8
  • 20

5 Answers5

3

Looks like the framework was poorly designed. They should've put an interface on all the ones that support tracking mileage so you can cast to that if available and extract the mileage from the interface.

Since you mentioned not having control over the framework classes, you only have a couple options. You can either try to detect its type and cast it to pull out the mileage or use reflection. The latter is probably going to be your best bet.

See Use reflection to get the value of a property by name in a class instance for good examples of how to get property values.

The big difference for you is since you don't know for sure that the Mileage property will exist, you will need to do checks after the type.GetProperty(...) calls.

EDITED TO ADD SAMPLES

Using Reflection:

static void Main(string[] args)
    {
        Audi _newCar = new Audi() { Mileage = 10 };
        Car myCar = _newCar;

        // Using Reflection
        var propInfo = myCar.GetType().GetProperty("Mileage");
        if (propInfo != null)
        {
            Console.WriteLine(propInfo.GetValue(myCar));
        }

        // Using dynamic
        dynamic myCarDyn = myCar;

        Console.WriteLine(myCarDyn.Mileage);
    }
Community
  • 1
  • 1
Travis
  • 689
  • 5
  • 11
  • Good catch, @nodots. Not sure why I blind spotted that option in my original response. – Travis Apr 03 '15 at 14:23
  • Hey Travis, I know that this property exists for each class that can be given. I am not sure how to translate the link you gave into this example. Could you give an example for this setup? – Bastiaan Apr 03 '15 at 14:28
  • I used the dynamic approach and it works brilliantly. I have rewritten the code and could remove almost 50%! I did have to reference Microsoft.CSharp to get it working and change some methods to have their arguments casted to a specific type to get Linq working, but it works like a charm. Thanks! – Bastiaan Apr 03 '15 at 15:52
2

Looks like you have to fight with a poor framework. Possible ways to overcome this would be the use of reflection or dynamic. If there are many possible values. If you know there are only a few possibilities and it's ok in this context to build a dependency to them, you can just check for the exact type and cast to it.

treze
  • 3,159
  • 20
  • 21
  • Hey Treze, if I cast to the exact type, it would mean that I have to make variations for all possible types in my code right? – Bastiaan Apr 03 '15 at 14:29
0

This is how it should be done:

public class Car
{     
    public int Mileage
    {
        get ;
        set ;
    }   
}

public class Audi : Car
{
    public override string ToString()
    {
        return "I'm a Audi";
    }
}

public class BMW : Car
{
    public override string ToString()
    {
        return "I'm a BMW";
    }
}

public class Program
{
    //outside this class either a BMW class or Audi class is instantiated
    Audi _newCar = new Audi();

    // I don't know which one it is so I use a generic type
    Car MyCar;

    int Mileage;

    Program()
    {
        // Now I cast the unknown class to the car type
        MyCar = _newCar;

        // Although I know both Audi & BMW have the Mileage property, I cannot use it
        Mileage = MyCar.Mileage;
    }
}

This the Mileage exist for all the cars

Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142
0

I would use reflection to get the property:

try
{
    Mileage = (int)MyCar.GetType().GetProperty("Mileage").GetValue(MyCar, null);
}
catch (Exception e)
{
    // in this case, the instance has no property named "Mileage"
}

Don't forget to import the right namespace:

using System.Reflection;
Martin Wantke
  • 4,287
  • 33
  • 21
-1

Multilevel inheritance is one of the option, try it

public class Car {

}

public class MyCustomizedCar : Car { private int _Mileage; public int Mileage { get { return _Mileage; } set { _Mileage = value;} } }

public class Audi : MyCustomizedCar {

}

public class BMW : MyCustomizedCar {

}

sudhakar kutti
  • 169
  • 1
  • 11