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

C# 使用不带反射的字符串获取属性,c#,winforms,reflection,interface,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";

对象类

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;
我还想这样设置属性

字符串PathToProperty=“s.Building1.Room1.value1”
SelectedValue=路径属性

原因是我通过将一组组合框中的文本串在一起来创建PathTopProperty。最终,我希望避免随着组合框内选项的增加而添加到IF语句列表中

我一直在搞反射,但为了避免这种情况,我在某个地方读到了一些关于接口的文章(使用它们来公开属性),但我不知道怎么做


如果反射是最好的选择,有人能告诉我两种获取属性的方法和另一种设置属性的方法吗?

我建议您采取不同的方法。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];
    }
}
教室
{
//和你的一样
}
班级建设
{
公共列表室{get;set;}
公共建筑()
{
房间=新列表();
房间。添加(新房间());
房间。添加(新房间());
//获取“room#x”->var room=objBuilding.Rooms[x];
//获取“建筑物i中的房间x”->var room=objStreet.Buildings[i].Rooms[x];
}
}
阶级街
{
公共列表建筑物{get;set;}
公共街()
{
建筑物=新列表();
建筑物。添加(新建筑物());
建筑物。添加(新建筑物());
建筑物。添加(新建筑物());
建筑物。添加(新建筑物());
//获取“building#i”->var building=objStreet.Buildings[i];
}
}

我建议您采取不同的方法。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];
    }
}
教室
{
//和你的一样
}
班级建设
{
公共列表室{get;set;}
公共建筑()
{
房间=新列表();
房间。添加(新房间());
房间。添加(新房间());
//获取“room#x”->var room=objBuilding.Rooms[x];
//获取“建筑物i中的房间x”->var room=objStreet.Buildings[i].Rooms[x];
}
}
阶级街
{
公共列表建筑物{get;set;}
公共街()
{
建筑物=新列表();
建筑物。添加(新建筑物());
建筑物。添加(新建筑物());
建筑物。添加(新建筑物());
建筑物。添加(新建筑物());
//获取“building#i”->var building=objStreet.Buildings[i];
}
}

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


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

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


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

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

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

我向你提出以下解决办法:

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

反射是一种明确设计的工具,用于执行您试图执行的操作。为什么你认为这是一个坏的选择?-我不能让它正确工作B -每个人都说你应该避免它,如果反射是最好的方式,那么我将如何得到和设置属性,你应该考虑使用数组或列表。它们可以被编入索引,看起来更符合你想要实现的目标。或者是一本字典。反射是一个明确设计用来做你想做的事情的工具。为什么你认为这是一个坏的选择?-我不能让它正确工作B -每个人都说你应该避免它,如果反射是最好的方式,那么我将如何得到和设置属性,你应该考虑使用数组或列表。它们可以被编入索引,看起来更符合你想要实现的目标。或者是一本字典。谢谢你的回答。虽然我不知道如何使用它,但我需要能够使用建筑名称而不是数字访问它。这就是为什么我说:重新设计/重构其他部分。您可以拆分字符串,提取数字,然后使用它们。请记住,数组/列表索引是从零开始的,而数字可能从1.var pathParts=PathToProperty.Split('.');//一个startOk我想我知道你得到了什么抱歉,我想通过尝试创建一个更简单的我的实际项目的例子,我没有足够的细节。我将编辑这个问题。。这些建筑将不会被称为building1、building2等,而是可以被称为bob、steve、sue等;房间也一样,所以他们不会有任何与之相关的数字。谢谢你的回答。不过我不确定如何使用它,我需要能够使用建筑名称而不是数字访问它。这就是为什么我说:重新设计/重构其他部分。您可以拆分字符串,提取数字,然后使用它们。记住