1

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?

3
  • 1
    Reflection is the tool explicitly designed to do what you're trying to do. Why do you think it's a bad option? Commented Mar 3, 2016 at 13:19
  • A- I can't get it to work correctly B - everyone says you should avoid it if reflection is the best way then how would i both get and set the property Commented Mar 3, 2016 at 13:23
  • You should consider using Arrays or Lists. They can be indexed and seem to fit more closely what you are trying to achieve. Or a Dictionary perhaps. Commented Mar 3, 2016 at 13:28

3 Answers 3

3

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];
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for answer not sure how i use it though, i need to be able to access it using the building name not a number.
That is why I said: redesign/refactor other parts as well. You can split the string, extract the numbers and then use them. And remember that Array/List indexes are zero-based, while your numbers may be starting at 1.
var pathParts = PathToProperty.Split('.'); // a start
Ok I think i know what you are getting at
Sorry I think by trying to create a simpler example of my actual project I have not been details enough. I will edit question.. the buildings will not be called building1, building2 etc. instead then could for example be called, bob, steve, sue; same for rooms so they will in no way have a number associated with them.
|
1

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.

Comments

0

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);
            }
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.