使用字符串

时间:2016-01-27 08:49:47

标签: c# reflection

这里有很多关于反思的东西,但我似乎无法理解我的具体问题。

我的课程:

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

4 个答案:

答案 0 :(得分:4)

由于b1b2是字段,您可以使用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查询。一切都没有反思!

我猜你已经找到了答案,但我认为这很有趣。希望它可以帮到某人。