My CTO (Chief Technical Officer) asked me to come up with a way where he could write one single function in the base class, and have access to the all the properties of the child class. Here is what I came up with -
Base Class
class Assets
{
public Assets getPropertyVal(Assets asObj)
{
PropertyInfo[] propInfos = asObj.GetType().GetProperties();
string strAttributeValue = "10";
foreach (PropertyInfo propInfo in propInfos)
{
// Getting the value
var propValue = propInfo.GetValue(asObj, null);
// Setting the value
propInfo.SetValue(asObj, Convert.ChangeType(strAttributeValue, propInfo.PropertyType), null);
}
return asObj;
}
}
Child Class
class House : Assets
{
public int rooms{get; set;}
}
Program.cs file
class Program
{
static void Main(string[] args)
{
House hsObj = new House();
hsObj.rooms = 5;
Assets asObj = hsObj.getPropertyVal(hsObj);
// Returns asObj as JSON
}
}
Now this works fine, but I was just wondering if there was a better way to do this in C#.
Note that we do not know what properties will be present in the child class, so this will have to be determined at run-time.
UPDATE : Making it clear, I was just wondering if there is a better way to access the child class properties, one without using reflection. The important point to note is that we have no idea what properties a child class may have.
UPDATE #2 : I am working with a product that has many entities. These entities have different properties. I want to be able to access and work with all these properties in one single place. This function is exactly that. It's that one single place from where I can access all the data.
First, your Program.cs doesn't actually "do" what you say you want. It sounds like you want a program so that you can do this:
Asset myAsset = new House();
myAsset.Rooms = 5;
But, why would you even want to do that anyway? If your asset isn't a House, it will throw an exception, so you will need to check that first:
if (myAsset is House)
myAsset.Rooms = 5;
At that point, you might as well just cast it to a House though. It sounds like you may want to use a PropertyBag or Dictionary instead of inheritance.
I think what you are describing is this. Note that option 1 doesn't really restrict which properties can be used on which classes, so I'm guessing this won't really work for your specific case.
// Option 1, a Property Bag (Note: this replaces the properties on the classes)
class Asset
{
Dictionary<string, object> myPropertyBag = new Dictionary<string, object>();
public T GetProperty<T>(string property)
{
// This throws if the property doesn't exist
return (T)myPropertyBag[property];
}
public void SetProperty<T>(string property, T value)
{
// This adds the property if it doesn't exist
myPropertyBag[property] = (object)value;
}
}
// Option 2, use a switch and override this function in derived classes
class Asset
{
public int SomePropertyOnAsset { get; set; }
public virtual T GetProperty<T>(string property)
{
switch (property)
{
case "SomePropertyOnAsset": return this.SomePropertyOnAsset;
default: throw new ArgumentException("property");
}
}
public virtual void SetProperty<T>(string property, T value)
{
switch (property)
{
case "SomePropertyOnAsset": this.SomePropertyOnAsset = (int)value;
default: throw new ArgumentException("property");
}
}
}
class House : Asset
{
public int Rooms { get; set; }
public virtual T GetProperty<T>(string property)
{
switch (property)
{
case "Rooms": return this.Rooms;
default: return base.GetProperty<T>(property);
}
}
public virtual void SetProperty<T>(string property, T value)
{
switch (property)
{
case "Rooms": this.Rooms = (int)value;
break;
default: base.SetProperty<T>(property, value);
break;
}
}
}
Then, this is how you use them:
// Option 1
Asset asset = new House();
asset.SetProperty("Rooms", 5);
var rooms = asset.GetProperty<int>("Rooms");
// Option 2
Asset asset = new House();
asset.SetProperty("Rooms", 5);
asset.SetProperty("SomePropertyOnAsset", 10);
asset.SetProperty("SomethingElse", 15); // Throws ArgumentException
A 3rd option is to make Asset a DynamicObject. http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.aspx
If you can't or don't want to make a major change to your Asset base class or touch every entity, you will probably need to use reflection.