从变量中获取“name”属性

时间:2017-11-03 14:11:46

标签: c#

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

这样的事情:

如果我有3个名为bt1bt2bt3的按钮,则图片路径是我的图片=“\”的路径。

int btnum = 1;
bt + num .backgroundpicture=picturepath+num+".png";    
btnum +=1;
bt + num .backgroundpicture=picturepath+num+".png";
btnum +=1;
bt + num .backgroundpicture=picturepath+num+".png";

因此,应将backgroundpicture的{​​{1}}设置为bt1picturepath1.png设置为backgroundpicturebt2和{{1} bt3到picturepath2.png

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

3 个答案:

答案 0 :(得分:2)

您不应该依赖变量的名称,因为那些可能会发生变化的实现细节。

不是让三个变量引用一个按钮,而是使用包含所有按钮的列表并引用由索引指定一个:

var buttons = new List<Button> { btn1, btn2, btn3 };
buttons[btnNumber - 1].BackGroundImage = ...

请注意,数组和列表是从零开始的,因此您必须减去一个。例如。获得btn1你需要buttons[0]

答案 1 :(得分: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;
        }

那应该做你想要的。

由于您希望在运行代码时创建一个未指定数量的对象,因此最好动态创建按钮并在窗体(或文本或其他)上设置位置。那个循环。

答案 2 :(得分:0)

另一种方法是,如果你想真正访问和影响某些对象,基于它具有的属性(动态),并且仍然没有完全DLR的网格,请使用Linq表达式:

所以对某些对象(例子)

public class ExampleClass {
  public Button bt1 { get; set; }
  public Button bt2 { get; set; }
  .....
}

您可以从属性中构建一个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();

现在,此示例方法是工厂方法构建器,将分配逻辑定义为二进制表达式,收集这些并构建一个Action - 然后根据您的要求,它可以按类型重用。您也可能会注意到,将ExampleClass与Generic Argument交换并将约束类型转换为类是非常简单的:

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

如果由于某种原因您只想限制为Button类型,则MemberExpressions是优秀的元数据处理程序,比使用直接反射/ Activator代码更有效。这允许您动态收集所有看起来像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