2013-01-07 58 views
0

我不確定從哪裏開始。我正在使用我的實體組件模型庫爲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文檔,並做到以下幾點。 任何具有類型屬性的標籤都將作爲它們表示的類型添加到表單中。例如,我有一個表示圖像的Image類,該示例中的BGImage應該創建一個Image並將其添加到表單中。我需要的是一種將type =「Image」與類Image相關聯的方法。

我已經有了一個方法來將實體添加到遊戲中,我的問題在於一種將字符串變爲類型並從中實例化新實體的方法。

我想要做的是從字符串中返回一個類型,我不太確定這是可能的。有沒有辦法在C#中做到這一點,或者我從錯誤的角度來攻擊它?

+4

請問您能否提供一些代碼示例並深入探討問題的背景?因此,我們會有更多的細節爲您的問題提供更好的,一致的答案。 –

+0

問題是我沒有任何代碼示例,我不確定從哪裏開始。我會看看我是否可以更詳細地解釋 – redcodefinal

+0

那太棒了。想象一下,如果你不太明白這個問題,那麼對我們來說有多困難)無論如何,謝謝你的理解。 –

回答

3

是的,您可以使用C#類型限定名完全按照您的描述進行操作。

例如,System.Drawing.Image的限定名稱是「System.Drawing.Image,System.Drawing」。合格的名稱由幾塊組成。在我的例子中,它是[類型名稱],[程序集名稱]。 (Reference article from msdn

只要包含類型加載到您的應用程序域(在這種情況下,組件System.Drawing中)組裝,你可以做下面的實例吧:

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

嗯,這個可能會工作。我需要能夠將新對象添加到列表中。它不需要有一個字段,所以它可以是'AddEntity(new Image());'。我可以用這種方法做到這一點嗎? – redcodefinal

+0

Erm no,AddEntity(Activator.CreateInstance(imageType));雖然 –

+0

這似乎是會起作用的,我現在正在編寫一個原型。 :) – redcodefinal

0

待辦事項你自己一個忙,並將類型在你的xml中的映射存儲到另一個資源中的程序集中的具體類型。特別是如果你開始定義/擴展你自己的類型。

例如

<Assembly name="System.Drawing", namespace = "System.Drawing"> 
<Type name = "PrettyPicture", Type = "Image"/> 
</Assembly> 

將完全合格的名稱在佈局文件,你會被所有的地方,如果你想改變什麼。

dtyron與他在Type.GetType和Activator.CreateInstance指向幾乎給你一個好的開始堅果和螺栓。

+1

或序列化爲二進制 –

0

您可以編寫完整的解析器。這不像其他解決方案那麼簡單,但從長遠來看可能會更簡單。

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; 

    } 
}