C# 获得;名称“;来自变量的属性

C# 获得;名称“;来自变量的属性,c#,C#,我想要一个c#应用程序,在该应用程序中,我可以使用int变量或保存在数组中的名称修改指定对象(不过我更喜欢使用int) 大概是这样的: 如果我有3个名为bt1、bt2和bt3的按钮,图片路径是指向图片所在位置的路径=“\” 因此,它应该将bt1的backgroundpicture设置为picturepath1.png,将bt2的backgroundpicture设置为picturepath2.png,将bt3的backgroundpicture设置为picturepath3.png (在现实场景

我想要一个c#应用程序,在该应用程序中,我可以使用int变量或保存在数组中的名称修改指定对象(不过我更喜欢使用int)

大概是这样的:

如果我有3个名为
bt1
bt2
bt3
的按钮,图片路径是指向图片所在位置的路径=“\”

因此,它应该将
bt1的
backgroundpicture
设置为
picturepath1.png
,将
bt2的
backgroundpicture
设置为
picturepath2.png
,将bt3的
backgroundpicture
设置为
picturepath3.png


(在现实场景中,我将使用一个或多个对象,或者在运行代码时创建未指定数量的对象。)

您不应该依赖变量的名称,因为这些是可能更改的实现细节

不要让三个变量分别引用一个按钮,而是使用包含所有按钮的列表,并通过其索引引用指定的按钮:

var buttons = new List<Button> { btn1, btn2, btn3 };
buttons[btnNumber - 1].BackGroundImage = ...
var按钮=新列表{btn1,btn2,btn3};
按钮[btnNumber-1]。背景图像=。。。

请注意,数组和列表是基于零的,因此必须减去一。例如,要获取
btn1
您需要
按钮[0]

只需将其放入一个循环中,如下所示:

        int BtnNum = 1;
        int BtnNumUWant = 3;

        int X = 10;
        int Y = 10;

        string pictureName = "picturepath";

        while (BtnNum < BtnNumUWant + 1)
        {
            Button Btn = new Button();
            Btn.Name = "Btn" + BtnNum.ToString();
            Btn.BackgroundImage = Image.FromFile(Path.Combine(path, pictureName + BtnNum.ToString() + ".png"));
            Btn.Location = new Point(X, Y);
            Btn.Text = Btn.Name;
            Btn.Parent = this;

            BtnNum++;
            Y += 100;
        }
intbtnnum=1;
int BtnNumUWant=3;
int X=10;
int Y=10;
字符串pictureName=“picturepath”;
而(BtnNum
那应该是你想要的


由于您希望“在运行代码时创建未指定数量的对象”,因此最好动态创建按钮,并在该循环中的表单(或文本或任何内容)上设置位置。

如果您希望根据对象的属性真正访问并影响某个对象,则另一种方法是(动态)在完整DLR中仍然没有脱离网格是使用Linq表达式:

所以对于某些对象(示例)

您可以从属性构建一个mutator工厂,并动态地创建赋值,如下所示:

var instance = Expression.Parameter(typeof(ExampleClass));
Where子句是可选的——只是根据您的情况进行了调整

var propertiesAffected = instance.Type.GetProperties().Where(x => RegEx.IsMatch(x.Name, "[A-Za-z]+\d+")).Select(p => Expression.MakeMemberAccess(instance, p)).ToList();
现在,这个示例方法是一个工厂方法生成器,将赋值逻辑定义为一个二进制表达式,收集它们并构建一个操作——然后根据您的需求,它可以根据类型重用。另外,您可能会注意到,将ExampleClass与泛型参数和类型约束交换到类是很简单的:

public Action<T> BuildAssignments<T>(Expression instance, IEnumerable<MemberExpression> propertiesAffected) where T : class {
List<Expression> operations = new List<Expression>();
foreach (var pr in propertiesAffected) {
                              int num;
                              string extract = RegEx.Match(pr.Name, "(\d+)$").Value;
                              if (!string.IsNullOrWhitespace(extract)) {
                                 num = Int.Parse(extract);
          // This is to wrap the calculated value as a constant value                       
          var target = Expression.Constant($"{picturepath}{num}.png");
                              // Assign the property access of BackgroundPicture from pr (so the idea of instance.bt1.BackgroundPicture) to the templated value constructed


             operations.Add(Expression.Assign(Expression.PropertyOrField(pr, "BackgroundPicture"), target));
                              }
                             }

                             return Expression.Lambda<Action<ExampleClass>>(operations, instance).Compile();
                     }
public Action BuildAssignments(表达式实例,IEnumerable属性有效),其中T:class{
列表操作=新建列表();
foreach(受影响财产的var pr){
int-num;
字符串extract=RegEx.Match(pr.Name,“(\d+)$”).Value;
如果(!string.IsNullOrWhitespace(extract)){
num=Int.Parse(提取);
//这是将计算值包装为常量值
var target=Expression.Constant($“{picturepath}{num}.png”);
//将BackgroundPicture从pr的属性访问权(例如instance.bt1.BackgroundPicture)分配给构造的模板值
Add(Expression.Assign(Expression.PropertyOrField(pr,“BackgroundPicture”),target);
}
}
返回表达式.Lambda(操作,实例).Compile();
}
如果出于某种原因您希望仅限于按钮类型,那么MemberExpressions是优秀的元数据处理程序,比使用直接反射/激活器代码更有效。这允许您动态收集看起来像bt1、bt2或img1、img35的所有属性。。。并根据您的请求将它们分配给模板化输出名称,如果正确构建一次,则类型安全且性能极高,并在类型的生命周期中重复使用

这个电话的最终结果将是

var mutator = BuildAssignments<ExampleClass>(instance, propertiesAffected);
var model = new ExampleClass();
mutator(model);
// model will have properties assigned! This access is the reused item -- cache it early and save on processing
var mutator=BuildAssignments(实例、属性受影响);
var模型=新的ExampleClass();
突变子(模型);
//模型将具有指定的属性!此访问是重复使用的项--尽早缓存它并在处理时保存

使用适当的标记,这是什么类型的应用程序?对我来说似乎是一个“请做我的家庭作业”的问题…这是visual studio 2017中的一个c#程序,我使用的示例不是我计划首先使用它的真实程序。它是一个2d测试程序,更多的是尝试一些新的东西,使我的代码更小。这将创建不必要的按钮。但是OP只想修改现有的一个。@HimBromBeere因为他说“我将在运行代码时创建数量不确定的对象”,所以我认为在代码执行之前创建按钮毫无意义。通过代码管理它们会更容易,特别是如果他想让用户设置
BtnNumUWant
public Action<T> BuildAssignments<T>(Expression instance, IEnumerable<MemberExpression> propertiesAffected) where T : class {
List<Expression> operations = new List<Expression>();
foreach (var pr in propertiesAffected) {
                              int num;
                              string extract = RegEx.Match(pr.Name, "(\d+)$").Value;
                              if (!string.IsNullOrWhitespace(extract)) {
                                 num = Int.Parse(extract);
          // This is to wrap the calculated value as a constant value                       
          var target = Expression.Constant($"{picturepath}{num}.png");
                              // Assign the property access of BackgroundPicture from pr (so the idea of instance.bt1.BackgroundPicture) to the templated value constructed


             operations.Add(Expression.Assign(Expression.PropertyOrField(pr, "BackgroundPicture"), target));
                              }
                             }

                             return Expression.Lambda<Action<ExampleClass>>(operations, instance).Compile();
                     }
var mutator = BuildAssignments<ExampleClass>(instance, propertiesAffected);
var model = new ExampleClass();
mutator(model);
// model will have properties assigned! This access is the reused item -- cache it early and save on processing