C# 从字符串返回类型

C# 从字符串返回类型,c#,C#,我真的不知道从哪里开始。我正在使用实体组件模型库为XNA编写GUI管理器。我希望能够将XML文档动态导入GUI表单。我的想法是拥有一个包含控件类型的属性“type”。例如,type=“Image”会告诉解析器生成一个图像。一旦有了这些值,它就可以调用自己的XML解析方法来填充这些值。然而,我被困在这一部分 考虑这份文件: <Gui> <BGImage type="Image"> <Body> <Position>

我真的不知道从哪里开始。我正在使用实体组件模型库为XNA编写GUI管理器。我希望能够将XML文档动态导入GUI表单。我的想法是拥有一个包含控件类型的属性
“type”
。例如,
type=“Image”
会告诉解析器生成一个图像。一旦有了这些值,它就可以调用自己的XML解析方法来填充这些值。然而,我被困在这一部分

考虑这份文件:

<Gui>
  <BGImage type="Image">
    <Body>
      <Position>
        <X>0</X>
        <Y>0</Y>
      </Position>
    </Body>
    <ImageRender>
      <Texture>background</Texture>
      <Color>
        <R>255</R>
        <G>255</G>
        <B>255</B>
        <A>255</A>
      </Color>
    </ImageRender>
  </BGImage>
  <CheckBox type="Checkbox">
    <Body>
      <Position>
        <X>20</X>
        <Y>20</Y>
      </Position>
    </Body>
    <TileRender>
      <Index>0</Index>
      <Texture>checkbox</Texture>
      <Color>
        <R>255</R>
        <G>255</G>
        <B>255</B>
        <A>255</A>
      </Color>
    </TileRender>
    <TextRender>
      <Text>Checkbox</Text>
      <Font>spritefont</Font>
    </TextRender>
  </CheckBox>
</Gui>

0
0
背景
255
255
255
255
20
20
0
复选框
255
255
255
255
复选框
雪碧峰
我想做的是让一个类解析这个XML文档并执行以下操作。 任何具有类型属性的标记都将作为它们所表示的类型添加到表单中。例如,我有一个代表图像的图像类,示例中的BGImage应该生成一个图像并添加到表单中。我需要的是一种将type=“Image”与类映像关联起来的方法

我已经有了一个向游戏中添加实体的方法,我的问题在于如何使字符串成为一种类型并从中实例化一个新实体


我想做的是从字符串返回一个类型,我不确定这是否可行。在C#中有什么方法可以做到这一点,或者我从错误的角度来攻击它吗?

是的,您可以使用C#type限定名完全按照您所描述的方式来做

例如,
System.Drawing.Image
的限定名称是“System.Drawing.Image,System.Drawing”。限定名称由几个部分组成。在我的示例中,它是[类型名称],[程序集名称]。()

只要包含该类型的程序集加载到您的应用程序域中(在本例中,该程序集是System.Drawing),您就可以执行以下操作来实例化它:

var imageType = Type.GetType("System.Drawing.Image, System.Drawing");
System.Drawing.Image image = Activator.CreateInstance(imageType );

是的,通过使用C#类型限定名,您可以完全按照您所描述的操作

例如,
System.Drawing.Image
的限定名称是“System.Drawing.Image,System.Drawing”。限定名称由几个部分组成。在我的示例中,它是[类型名称],[程序集名称]。()

只要包含该类型的程序集加载到您的应用程序域中(在本例中,该程序集是System.Drawing),您就可以执行以下操作来实例化它:

var imageType = Type.GetType("System.Drawing.Image, System.Drawing");
System.Drawing.Image image = Activator.CreateInstance(imageType );

帮自己一个忙,并将从xml中的类型到程序集中的具体类型的映射存储在其他资源中。尤其是当您开始定义/扩展自己的类型时

e、 g


将完全限定的名称放在布局文件中,如果您想更改任何内容,您将到处都是


dtyron在Type.GetType和Activator.CreateInstance上的观点为您提供了一个良好的开端。

帮自己一个忙,将类型映射存储在xml中,并将其映射到其他资源中程序集中的具体类型。尤其是当您开始定义/扩展自己的类型时

e、 g


将完全限定的名称放在布局文件中,如果您想更改任何内容,您将到处都是


dtyron在Type.GetType和Activator.CreateInstance上的观点为您提供了一个良好的开端。

您可以编写一个完整的解析器。这并不像其他解决方案那么简单,但从长远来看可能更简单

    Control Parse(XElement element)
    {
        var root = new XElementControlPair(element, ControlWrapper.Create(element));

        var stack = new Stack<XElementControlPair>();

        stack.Push(root);

        while (stack.Any()) //here we recursively search for any child elements
        {
            var elem = stack.Pop();

            var children = from child in elem.XElement.Elements() 
                           let ctl = ControlWrapper.Create(child)                               
                           where child.Attribute("type") != null 
                           select new XElementControlPair(child, ctl);


            foreach (var child in children)
            {
                stack.Push(child);
                elem.Control.Controls.Add(child.Control);
            }

        }

        return root.Control.MakeControl();

    }

class XElementControlPair
{
    public XElement XElement { get; private set; }
    public ControlWrapper Control { get; private set; }

    public XElementControlPair(XElement elem, ControlWrapper ctl)
    {
        this.XElement = elem;
        this.Control = ctl;
    }
}

abstract class ControlWrapper
{
    public List<ControlWrapper> Controls { get; private set; }
    protected readonly XElement element;

    public ControlWrapper(XElement element)
    {
        this.element = element;
    }

    public static ControlWrapper Create(XElement element)
    {
        var type = element.Attribute("type").Value.ToLower();

        switch (type)
        {
            case "image":
                return new ImageWrapper(element);

            case "textbox":
                return new TextBoxWrapper(element);

            case "checkbox":
                return new CheckBoxWrapper(element);

            //etc...
        }
    }

    protected abstract Control _MakeControl(); //here is where you tell it how to construct a particular control given an XElement

    public Control MakeControl()
    {
        var ctl = _MakeControl();

        foreach (var child in Controls)
            ctl.Children.Add(child.MakeControl());

        return ctl;
    }

}

您可以编写完整的解析器。这并不像其他解决方案那么简单,但从长远来看可能更简单

    Control Parse(XElement element)
    {
        var root = new XElementControlPair(element, ControlWrapper.Create(element));

        var stack = new Stack<XElementControlPair>();

        stack.Push(root);

        while (stack.Any()) //here we recursively search for any child elements
        {
            var elem = stack.Pop();

            var children = from child in elem.XElement.Elements() 
                           let ctl = ControlWrapper.Create(child)                               
                           where child.Attribute("type") != null 
                           select new XElementControlPair(child, ctl);


            foreach (var child in children)
            {
                stack.Push(child);
                elem.Control.Controls.Add(child.Control);
            }

        }

        return root.Control.MakeControl();

    }

class XElementControlPair
{
    public XElement XElement { get; private set; }
    public ControlWrapper Control { get; private set; }

    public XElementControlPair(XElement elem, ControlWrapper ctl)
    {
        this.XElement = elem;
        this.Control = ctl;
    }
}

abstract class ControlWrapper
{
    public List<ControlWrapper> Controls { get; private set; }
    protected readonly XElement element;

    public ControlWrapper(XElement element)
    {
        this.element = element;
    }

    public static ControlWrapper Create(XElement element)
    {
        var type = element.Attribute("type").Value.ToLower();

        switch (type)
        {
            case "image":
                return new ImageWrapper(element);

            case "textbox":
                return new TextBoxWrapper(element);

            case "checkbox":
                return new CheckBoxWrapper(element);

            //etc...
        }
    }

    protected abstract Control _MakeControl(); //here is where you tell it how to construct a particular control given an XElement

    public Control MakeControl()
    {
        var ctl = _MakeControl();

        foreach (var child in Controls)
            ctl.Children.Add(child.MakeControl());

        return ctl;
    }

}

您能提供一些代码示例并深入了解问题的上下文吗?因此,我们会有更多的细节来更好、连贯地回答您的问题。问题是我没有任何代码示例,我真的不知道从哪里开始。我看看能不能更详细地解释一下,那太好了。想象一下,如果你不太理解这个问题,那么对我们来说有多困难)无论如何,谢谢你的理解。没有看到你尝试过的东西。。。尝试使用
switch
语句设置
var
变量?问题是,当我添加额外的GUI组件时,维护代码变得很困难,因为我必须为每种类型的GUI组件添加一个case条件。我认为必须有一个更简单的方法来做到这一点。我添加了一些额外的细节。您能提供一些代码示例并深入了解问题的上下文吗?因此,我们会有更多的细节来更好、连贯地回答您的问题。问题是我没有任何代码示例,我真的不知道从哪里开始。我看看能不能更详细地解释一下,那太好了。想象一下,如果你不太理解这个问题,那么对我们来说有多困难)无论如何,谢谢你的理解。没有看到你尝试过的东西。。。尝试使用
switch
语句设置
var
变量?问题是,当我添加额外的GUI组件时,维护代码变得很困难,因为我必须为每种类型的GUI组件添加一个case条件。我认为必须有一个更简单的方法来做到这一点。我添加了一些额外的细节。嗯,这可能有用。我需要能够将新对象添加到列表中。它不需要有字段,所以它可以是
AddEntity(newimage())。我能用这个方法做到吗?Erm no,AddEntity(Activator.CreateInstance(imageType));我会认为这似乎是可行的,我现在正在编写一个原型嗯,这可能有用。我需要能够将新对象添加到列表中。它不需要有字段,所以它可以是
AddEntity(newimage())。我可以用这个方法吗?呃,不,加法(