Question

Is it possible to attach dynamic property to an object of user-defined class?

public class Room
{
    public int NumberOfDoors { get; set; }

    public int NumberOfWindows { get; set; }
}

then from other context:

Room room = new Room();

dynamic contact = new ExpandoObject();
contact.NumberOfWalls = 4;

and then somehow associate NumberOfWalls with room, as its property?

Update (Larger Picture):

as per @nawfal's suggestion

I have a cached List<Room> being iterated in a razor view (outside the themes folder), calling a

particular partial view (from the current theme) for each element. One of the theme needs an extra

property in Room. I only have access to modify code in that particular theme folder, the partial

views cshtml files (don't ask why).

So its basically:

(psuedocode)

Room.NoOfWalls = SomeHeavyLiftingProcess(Room.NoOfWindows, Room.NoOfDoors)


I am looking for a way o update the List<Room> rooms object with NoOfWalls in

HttpRuntime.Cache["rooms"] to avoid calling SomeHeavyLiftingProcess() with each request. The

goal is to inject a property in cached object. Unfortuntely HttpRuntime.Cache["rooms"] is object

type and doesn't allow me to do this:

HttpRuntime.Cache["rooms"][3]["NoOfWalls"] = SomeHeavyLiftingProcess(..)

So I am thinking, for the first request (when cache is empty or invalid):

  • Unpackig: Retrieve (List<Room>)HttpRuntime.Cache["room"], inject NoOfWalls in the current room object.

  • Repacking: Update List<Room> room with the new object and assign it back to HttpRuntime.Cache.


For the subsequent requests, the value of NoOfWalls will come from cached object @Model.NoOfWalls.

Was it helpful?

Solution

You cannot add properties not defined in a class to an existing instance, without using a dynamic object like ExpandoObject.

If you need to add members to an existing class, you can create a child class with a special constructor:

public class SpecialRoom : Room
{
    public SpecialRoom() { }

    public SpecialRoom(Room copy)
    {
        this.NumberOfDoors = copy.NumberOfDoors;
        this.NumberOfWindows = copy.NumberOfWindows;
    }

    public int NumberOfJacuzzis { get; set; }
}

Usage:

var room = new Room();
room.NumberOfDoors = 3;

var specialRoom = new SpecialRoom(room)
{
    NumberOfJacuzzis = 7
};

Or:

var listOfRooms = new List<Room>();
// ...
var listOfSpecialRooms = listOfRooms.Select(x => new SpecialRoom(x));
listOfSpecialRooms.ForEach(x => x.NumberOfJacuzzis = ComplexCalculation(x));

If you have an existing concrete object (like an instance of the Room class), you can convert it to a dynamic object with a method like this:

public static dynamic ConvertObjectToDynamic(object value)
{
    if (value == null)
    {
        return null;
    }

    IDictionary<string, object> dynamicObject = new ExpandoObject();
    var properties = value.GetType().GetProperties(
        BindingFlags.Public | BindingFlags.Instance);

    foreach (var propertyInfo in properties)
    {
        if (propertyInfo.GetIndexParameters().Length == 0)
        {
            var propertyValue = propertyInfo.GetValue(value);
            dynamicObject[propertyInfo.Name] = propertyValue;
        }
    }

    return dynamicObject;
}

Usage:

var room = new Room();
room.NumberOfDoors = 3;

dynamic dynamicObject = ConvertToDynamic(room);
dynamicObject.WhateverYouWant = 7;

Now dynamicObject.NumberOfDoors will be 3, and dynamicObject.WhateverYouWant will be 7.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top