这里有很多关于反思的东西,但我似乎无法理解我的具体问题。
我的课程:
public class Box
{
public string Name { get; set; }
public int Size { get; set; }
}
public class Pallet
{
public Box b1 = new Box();
public Box b2 = new Box();
}
创建对象的代码:
Pallet p = new Pallet();
p.b1.Size = 5;
p.b2.Size = 10;
显示所选框大小的代码:
MessageBox.Show(p.b1.Size.ToString());
我想在运行时使用字符串选择框。即。
string boxid = "b1";
Object myObj = p. + boxid;
MessageBox.Show(myObj.Size.ToString());
显然这段代码不起作用。在这种情况下,获取所选框的值的正确方法是什么5
?
答案 0 :(得分:4)
由于b1
和b2
是字段,您可以使用GetField
获取字段。在FieldInfo
上,调用GetValue
提供托盘实例以获取特定字段。
Box box = (Box)typeof(Pallet).GetField(boxId).GetValue(pallet);
答案 1 :(得分:4)
你可以用反射来完成这项工作,因为@PatrickHofman已经回答了,但我相信这里有更好的解决方案:使用字典。
如果您将这些框存储在表单中或类型Dictionary<string, Box>
的某个属性中,并在实例化时添加所谓的框,那么生活会更容易!
public class Form1 : Form
{
public Dictionary<string, Box> Boxes { get; } = new Dictionary<string, Box>();
public Form1()
{
Pallet p = new Pallet();
p.b1.Size = 5;
p.b1.Size = 10;
Boxes.Add("b1", p.b1);
}
}
...谁知道在哪里,您可以按照以下标识获取方框:
MessageBox.Show(Boxes[boxId].Size.ToString());
有时候我们倾向于认为运行时意味着反射,并且有更好的方法可以在没有反思的情况下解决很多问题。
不要误会我的意思:我不反对反思,我在用例需要时使用它。
答案 2 :(得分:2)
这个问题迫使我们做出很多假设。它可以更详细地说明你从哪里传递它。接收方是什么?它是同一个应用程序的另一个副本还是完全不同的东西(例如接收端是否有.net框架?)。
如果.net框架在接收端可用,那么我建议在发送之前使用二进制或XML序列化将对象包装成一个整齐的包裹。然后在另一端简单地反序列化它。这样,您甚至不需要考虑序列化过程中对象包含的内容,.net框架会为您完成所有操作。如果你可以在两端使用相同的类定义,那么这种方法并不需要你自己明确地使用反射。
如果这听起来对你有用,我可以举一个例子。请在评论中告诉我。
编辑:更多信息
这是一种并非完全可怕的方法...... 使用XmlSerialiser将您的类转换为XML字符串,然后将其加载到XmlDocument对象中。一旦它在那里,您可以使用XPath查询来提取XML的特定节点,并仅使用字符串遍历整个类结构(在XML中)。
这是一个来自Microsoft的优秀代码示例,用于完成此操作... https://code.msdn.microsoft.com/windowsdesktop/Manipulate-XML-in-memory-4b612d6b/view/SourceCode
正如您在下面的评论中所说,您的真实世界类将拥有许多属性和字段,这种方法可能是最健壮,最灵活的方式来满足您的需求。它在某种程度上可能是很好的版本证明。
答案 3 :(得分:1)
像可查询数据库一样使用XML的方法(有点像SQL,但有XPath语法)......
要尝试此操作,请将此代码转储到Visual Studio中的新控制台应用程序中。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication3
{
[Serializable]
public class Pallet
{
public class Box
{
public string Name { get; set; }
public int Size { get; set; }
}
public Box b1 = new Box();
public Box b2 = new Box();
}
class Program
{
static void Main(string[] args)
{
//create your object and populate it
Pallet p = new Pallet();
p.b1.Name = "Fred";
p.b1.Size = 5;
p.b2.Name = "Bob";
p.b2.Size = 10;
//#### wrap up the object into XML string ####
XmlSerializer xs = new XmlSerializer(typeof(Pallet), "PalletNS");
StringBuilder sb = new StringBuilder();
XmlWriterSettings xws = new XmlWriterSettings();
xws.Encoding = Encoding.UTF8;
XmlWriter xw = XmlWriter.Create(sb, xws);
xs.Serialize(xw, p); //generate the XML string
//#### pallet is now stored in XML string inside sb
Console.WriteLine(sb.ToString());
//#### unwrap the pallet into an Xml structure that you can query easily with strings
XmlDocument xdoc = new XmlDocument();
xdoc.PreserveWhitespace = true;
xdoc.LoadXml(sb.ToString());
/* The XML serialized class looks like this...
<?xml version="1.0" encoding="utf-16"?>
<Pallet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="PalletNS">
<b1>
<Name>Fred</Name>
<Size>5</Size>
</b1>
<b2>
<Name>Bob</Name>
<Size>10</Size>
</b2>
</Pallet>
*/
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
nsmgr.AddNamespace("x", "PalletNS");
//get a reference to the top of the XML tree
XmlElement root = xdoc.DocumentElement;
//run an XPathQuery to pull a node that we're interested...
//in english: "Grab the Name of the first b2 item"
XmlNode xn = root.SelectSingleNode("./x:b2/x:Name", nsmgr);
//and print it's name to the console...
Console.WriteLine("\n\n" + xn.InnerText);
Console.WriteLine("\n\nPress enter to quit.");
Console.ReadLine();
}
}
}
如果您希望用户能够对您的数据结构运行 ARBITRARY 查询,那么这将非常强大。他们可以用英语编写查询,您的应用程序可以将其转换为XPath查询。一切都没有反思!
我猜你已经找到了答案,但我认为这很有趣。希望它可以帮到某人。