Reputation: 804
The Object Classes...
class Room
{
public string Value1 { get; set; }
public string Value2 { get; set; }
public string Value3 { get; set; }
public Room()
{
this.Value1 = "one";
this.Value2 = "two";
this.Value3 = "three";
}
}
class Building
{
public Room Room-Bob { get; set; }
public Room Room-Steve{ get; set; }
public Building()
{
this.Room-Bob = new Room();
this.Room-Steve = new Room();
}
}
class Street
{
public Building Building-Black{ get; set; }
public Building Building-Blue { get; set; }
public Building Building-Yellow { get; set; }
public Building Building-White { get; set; }
public Street ()
{
this.Building-Black = new Building();
this.Building-Blue = new Building();
this.Building-Yellow = new Building();
this.Building-White = new Building();
}
}
What I am currently using to get the values...
class go
{
public void go()
{
string SelectedValue = "";
Street s = new Street();
string PathToProperty = "s.Building1.Room1.value1";
if(PathToProperty == "s.Building1.Room1.value1") { SelectedValue = s.Building1.Room1.Value1; }
if (PathToProperty == "s.Building1.Room1.value2") { SelectedValue = s.Building1.Room1.Value2; }
}
}
How I would like to get the values... or something similar
string PathToProperty = "s.Building1.Room1.value1";
SelectedValue = PathToProperty;
I would also like to set the property like this...
string PathToProperty = "s.Building1.Room1.value1";
SelectedValue = PathToProperty;
The reason being I am making the the PathToProperty by stringing together the text from a bunch of combo boxes. Ultimately I want to avoid having to add to my list of IF statements as the options inside the combo boxes increase.
I have being messing around with reflection but would like to avoid this , I read somewhere you can do this with interfaces (using them to expose properties) but I do not know how.
If Reflection is the best choice for this can someone show me 2 methods of to get the property and another to set it?
Upvotes: 1
Views: 4166
Reputation: 5151
I propose you the following solution:
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CSharp.RuntimeBinder;
using Binder = Microsoft.CSharp.RuntimeBinder.Binder;
namespace ConsoleApplication2
{
class Program
{
class Room
{
public string Value1 { get; set; }
public string Value2 { get; set; }
public string Value3 { get; set; }
public Room()
{
this.Value1 = "one";
this.Value2 = "two";
this.Value3 = "three";
}
}
class Building{
public Room Room1 { get; set; }
public Room Room2 { get; set; }
public Building()
{
this.Room1 = new Room();
this.Room2 = new Room();
}
}
class Street{
public Building Building1 { get; set; }
public Building Building2 { get; set; }
public Building Building3 { get; set; }
public Building Building4 { get; set; }
public Street()
{
this.Building1 = new Building();
this.Building2 = new Building();
this.Building3 = new Building();
this.Building4 = new Building();
}
}
public static void Main(string[] args)
{
string SelectedValue = "";
Street s = new Street();
string buildingPropertyAsString = "Building3";
var splittedPath = "s.Building1.Room1.Value1".Split('.');
var neededValue =
((s.GetProperty(splittedPath[1]) as Building).GetProperty(splittedPath[2]) as Room).GetProperty(
splittedPath[3]) as string;
}
}
public static class TypeExtentions
{
public static object GetProperty(this object o, string member)
{
if (o == null) throw new ArgumentNullException("o");
if (member == null) throw new ArgumentNullException("member");
Type scope = o.GetType();
IDynamicMetaObjectProvider provider = o as IDynamicMetaObjectProvider;
if (provider != null)
{
ParameterExpression param = Expression.Parameter(typeof(object));
DynamicMetaObject mobj = provider.GetMetaObject(param);
GetMemberBinder binder = (GetMemberBinder)Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, member, scope, new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(0, null) });
DynamicMetaObject ret = mobj.BindGetMember(binder);
BlockExpression final = Expression.Block(
Expression.Label(CallSiteBinder.UpdateLabel),
ret.Expression
);
LambdaExpression lambda = Expression.Lambda(final, param);
Delegate del = lambda.Compile();
return del.DynamicInvoke(o);
}
else {
return o.GetType().GetProperty(member, BindingFlags.Public | BindingFlags.Instance).GetValue(o, null);
}
}
}
}
Upvotes: 0
Reputation: 11
Maybe you should try to use a super class using the extends keyword that way you can use the methods and constructors from multiple classes inside of one object. for example if you have "building" as your super class and "street" and "room" as sub classes, and build the proper constructors within them you can just call the "building" object inside of your "go" class and have all the methods and data points from "street" and "room" usable inside of "go".
Edit: I didn't see the tag for c# I'm using Java but the principle of inheritance works throughout languages, so use the equivalent for your language.
Upvotes: 1
Reputation: 24222
I'd suggest you take a different approach. IMO reflection is not the way to go for these kinds of situations.
Start with this, then build from it - redesigning/refactoring other parts as well, of course:
class Room
{
// same as yours
}
class Building
{
public List<Room> Rooms { get; set; }
public Building()
{
Rooms = new List<Room>();
Rooms.Add(new Room());
Rooms.Add(new Room());
// get "room #x" -> var room = objBuilding.Rooms[x];
// get "room #x in building #i" -> var room = objStreet.Buildings[i].Rooms[x];
}
}
class Street
{
public List<Building> Buildings { get; set; }
public Street ()
{
Buildings = new List<Building>();
Buildings.Add(new Building());
Buildings.Add(new Building());
Buildings.Add(new Building());
Buildings.Add(new Building());
// get "building #i" -> var building = objStreet.Buildings[i];
}
}
Upvotes: 3