我想执行一个存储在字符串变量中的 C# 语句。例如:
string statement1 = "button1.Visible = true";
string statement2 = "button1.Text = \"Number\"";
我想执行一个存储在字符串变量中的 C# 语句。例如:
string statement1 = "button1.Visible = true";
string statement2 = "button1.Text = \"Number\"";
查看您的评论并且您有 80 个控件需要非常相似的操作,为此目的,动态编译可能是一种过度杀伤力。您可以使用Controls
父容器的使用集合以及Tag
按钮的属性来实现它。一个事件处理程序就足够了。
您可以使用 LINQ 成员,例如OfType
和Cast
来使您的代码更小。
编辑
查看您的最新评论后,您应该做的是以编程方式创建按钮并将它们添加到您Form
或您拥有的任何容器中。然后,您可以保留一个Dictionary<string, Button>
,让您可以遍历集合,或通过其名称访问单个按钮。就像是:
//Declare this globally
Dictionary<string, Button> Dic = new Dictionary<string, Button>(81);
//put this in the constructor
for(int i=0; i<81; i++)
{
Button b = new Button();
b.Text = i; //or Random or whatever
b.Name = "btn" + i.ToString();
this.Controls.Add(b);
Dic.Add(b.Name, b);
}
稍后您可以像这样进行两次迭代:
foreach(var item in Dic)
{
item.Value.Visible = true; //or false
}
和这样的基于密钥的访问:
Dic["btn45"].Visible = true; //or false
由于您正在创建数独,我可能认为您应该TableLayoutPanel
在设计时使用适当数量的行和列,然后将按钮添加到面板并在循环中设置它们的 Row/Column 属性。这将有助于更好地响应调整大小事件等。
从您的评论看来,您只是想迭代 80 多个类似的按钮并以相同的方式配置它们。这可以通过比执行动态代码简单得多的方式来完成。
这里有几种方法。
首先在设计器中为 80 个按钮中的每一个设置 Tag 属性为一个特定的数字。
然后执行这段代码:
foreach (var button in Controls.OfType<Button>().Where(button => button.Tag == "TAG"))
{
button.Visible = true;
button.Text = "Number";
}
确保所有 80 个按钮的名称为“buttonX”,其中 X 是一个数字。
然后执行这段代码:
foreach (var button in Controls.OfType<Button>().Where(button => button.Name.StartsWith("button"))
{
button.Visible = true;
button.Text = "Number";
}
如果,正如您在评论中所说,您只需要解决这个问题:“执行”这种类型的代码:
object.member=value
whereobject
是指存储在字段或属性中的内容。member
引用该对象的公共成员(字段或属性),并且value
始终可以轻松转换为成员类型,那么以下代码将起作用。
请注意,它缺少错误检查,因此请确保在使用之前检查代码。
另外,我一点也不相信这是合适的解决方案,但是由于您决定询问您想到的解决方案而不是实际问题,因此很难提出更好的解决方案。
您可以在LINQPad中运行此代码:
void Main()
{
button1.Dump();
SetProperties(this,
"button1.Visible=true",
"button1.Text=\"Number\""
);
button1.Dump();
}
public static void SetProperties(object instance, params string[] propertySpecifications)
{
SetProperties(instance, (IEnumerable<string>)propertySpecifications);
}
public static void SetProperties(object instance, IEnumerable<string> propertySpecifications)
{
var re = new Regex(@"^(?<object>[a-z_][a-z0-9_]*)\.(?<member>[a-z_][a-z0-9_]*)=(?<value>.*)$", RegexOptions.IgnoreCase);
foreach (var propertySpecification in propertySpecifications)
{
var ma = re.Match(propertySpecification);
if (!ma.Success)
throw new InvalidOperationException("Invalid property specification: " + propertySpecification);
string objectName = ma.Groups["object"].Value;
string memberName = ma.Groups["member"].Value;
string valueString = ma.Groups["value"].Value;
object value;
if (valueString.StartsWith("\"") && valueString.EndsWith("\""))
value = valueString.Substring(1, valueString.Length - 2);
else
value = valueString;
var obj = GetObject(instance, objectName);
if (obj == null)
throw new InvalidOperationException("No object with the name " + objectName);
var fi = obj.GetType().GetField(memberName);
if (fi != null)
fi.SetValue(obj, Convert.ChangeType(value, fi.FieldType));
else
{
var pi = obj.GetType().GetProperty(memberName);
if (pi != null && pi.GetIndexParameters().Length == 0)
pi.SetValue(obj, Convert.ChangeType(value, pi.PropertyType));
else
throw new InvalidOperationException("No member with the name " + memberName + " on the " + objectName + " object");
}
}
}
private static object GetObject(object instance, string memberName)
{
var type = instance.GetType();
var fi = type.GetField(memberName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Default);
if (fi != null)
return fi.GetValue(instance);
var pi = type.GetProperty(memberName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Default);
if (pi != null && pi.GetIndexParameters().Length == 0)
return pi.GetValue(instance, null);
return null;
}
private Button button1 = new Button();
public class Button
{
public bool Visible;
public string Text { get; set; }
}
This will output (the two button1.Dump();
statements) the button configuration before and after, and you'll notice that the property and the field have been set.
You can execute this as follows:
`SetProperties(this, "...", "...");
where this
must refer to your form object (the one that owns the buttons).
What about using delegates?
Action statement1 = () => button1.Visible = true;
Action statement2 = () => button1.Text = "Number";