从字符串返回类型
本文关键字:返回类型 字符串 | 更新日期: 2023-09-27 17:50:59
我真的不知道从哪里开始。我正在使用我的实体组件模型库为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>
我想做的是有一个类解析这个XML文档并执行以下操作。任何带有type属性的标记都会以其表示的类型添加到表单中。例如,我有一个代表图像的Image类,BGImage在这个例子中应该制作一个图像并添加到表单中。我需要的是一种将type="Image"与类Image关联起来的方法。
我已经有一个方法,我使用添加实体到游戏中,我的问题在于一种方法,使一个字符串的类型,并实例化一个新的实体。
我想做的是从字符串返回一个类型,我不确定这是可能的。在c#中是否有任何方法可以做到这一点,或者我从错误的角度攻击它?
是的,你可以通过使用c#类型限定名来做你所描述的。
例如,System.Drawing.Image
的限定名称为"System.Drawing"。形象,System.Drawing"。限定名由几个部分组成。在我的例子中,它是[类型名称],[程序集名称]。(参考文章来自msdn)
只要包含该类型的程序集被加载到您的应用程序域(在本例中,程序集是System.Drawing),您就可以执行以下操作来实例化它:
var imageType = Type.GetType("System.Drawing.Image, System.Drawing");
System.Drawing.Image image = Activator.CreateInstance(imageType );
帮自己一个忙,将从xml中的类型映射到其他资源中的程序集中的具体类型。尤其是当你开始定义/扩展你自己的类型时。
。
<Assembly name="System.Drawing", namespace = "System.Drawing">
<Type name = "PrettyPicture", Type = "Image"/>
</Assembly>
等把完全限定名放在布局文件中,如果你想改变任何东西,你就会到处都是。
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;
}
}
然后为每种控件创建一个包装器类,处理将XML转换为特定控件的问题。例如:
sealed class ImageWrapper : ControlWrapper
{
public ImageWrapper(XElement element) { } : base(element)
protected override Control _MakeControl()
{
var image = new Image();
var pos = element.Element("Position");
var x = int.Parse(pos.Element("X").Value);
var y = int.Parse(pos.Element("y").Value);
image.Position = new Point(x, y);
//continue setting other properties...
return image;
}
}