luke_t
luke_t

Reputation: 2975

Assign object to a class variable

I pass a dictionary into a method:

Dictionary<string, object> vehicles

The value of the dictionary can be either a class instance named Vehicle or a class instance that inherits from Vehicle, named Truck.

I have a DataTable that I then use a field row value to extract the dictionary value, using reflection.

Vehicle v = (Vehicle)vehicles[dt.Rows[0]["Reference"].ToString()]

PropertyInfo vehicleInfo = typeof(Vehicle).GetProperty("Height");
string propertyVal = vehicleInfo.GetValue(t, null).ToString();

The only problem is, if I try to extract a field value from the class Truck and the field is not inherited from Vehicle, then vehicleInfo is not an object due to being unable to get the property.

Is there a way I can dynamically access either Vehicle or Truck class properties using the above? Or is a completely different approach required?

Upvotes: 1

Views: 102

Answers (2)

Scott Hannen
Scott Hannen

Reputation: 29207

Ideally you'd want to prevent the problem by ensuring that you already know the type of your objects. If you have an object, you don't know its type, and you have to inspect it to see if it's a Truck or a Vehicle and see which properties it has, that's the underlying problem to solve. You don't want a method to take an object and then try to figure out what it is. Instead, fix it so that the type of the parameter is meaningful and tells the method everything that it needs to know about that parameter.

Without knowing the full details, you could try something like this:

public interface IVehicle
{
    decimal Height {get;}
}

This interface has the properties you expect. You write all your code using this interface.

Dictionary<string, IVehicle> vehicles

From now on, you never have to wonder what something is or which properties it has. It's an IVehicle, which tells you that it has all of the properties of IVehicle.

You still have the original problem - other classes that don't implement this interface. You can adapt then so that they do implement the interface. For example,

public class TruckToVehicleAdapter : IVehicle
{
    private readonly Truck _truck;

    public TruckToVehicleAdapter(Truck truck)
    {
        _truck = truck;
    }

    public decimal Height { get { return _truck.WhateverHeightPropertyThisHas; } }
}

That's just one approach. But the general idea is to avoid having a bunch of objects where you don't know their types. Instead, think of how to take the object you have and require it to be the type you want. Convert it, make a new object, write an adapter like in the above example. But then you'll know what you have.

And if another new type of object comes along you won't have to modify all your methods to see if your object is a Motorcycle or a RecreationalVehicle. That can get out of hand. You can just follow the same pattern. Make everything an IVehicle.

Upvotes: 2

Aen Sidhe
Aen Sidhe

Reputation: 1171

You could access it like this:

if (vehicle is Truck t)
     // t.FieldOfTruck

In role of vehicle can be even object

Upvotes: 1

Related Questions