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?
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
.
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.