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等;房间也一样,所以他们不会有任何与之相关的数字。谢谢你的回答。不过我不确定如何使用它,我需要能够使用建筑名称而不是数字访问它。这就是为什么我说:重新设计/重构其他部分。您可以拆分字符串,提取数字,然后使用它们。记住