使用不带反射的字符串获取属性

时间:2016-03-03 13:16:41

标签: c# winforms reflection interface

对象类......

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

        }

    }

我目前正在使用什么来获取价值......

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


    }

}

我希望如何获得价值......或类似的东西

string PathToProperty = "s.Building1.Room1.value1";    
SelectedValue = PathToProperty;

我还想像这样设置属性......

string PathToProperty =" s.Building1.Room1.value1&#34 ;;
SelectedValue = PathToProperty;

原因是我通过将来自一堆组合框的文本串在一起来制作PathToProperty。最终,我希望避免在组合框内的选项增加时添加到我的IF语句列表中。

我一直在搞乱反思,但是想避免这种情况,我在某​​处读到你可以用接口做这个(使用它们来暴露属性),但我不知道如何。

如果反射是最好的选择,有人可以告诉我两种获取财产的方法和另一种设置它的方法吗?

3 个答案:

答案 0 :(得分:3)

我建议你采取不同的方法。 IMO的反思不适合这种情况。

从这开始,然后从中构建 - 重新设计/重构其他部分,当然:

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

答案 1 :(得分:1)

也许您应该尝试使用 extends 关键字来使用超类,这样您就可以使用一个对象内多个类的方法和构造函数。例如,如果你将“building”作为你的超类,将“street”和“room”作为子类,并在其中构建适当的构造函数,你可以在你的“go”类中调用“building”对象并拥有所有“go”中可用的“街道”和“房间”的方法和数据点。

编辑:我没有看到c#的标签我正在使用Java,但继承原则适用于所有语言,因此请使用等效语言。

答案 2 :(得分:1)

我建议您使用以下解决方案:

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