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 ドキュメントを解析させ、次のことを実行させることです。type 属性を持つタグは、それらが表すタイプとしてフォームに追加されます。たとえば、画像を表す Image クラスがあり、例の BGImage は画像を作成してフォームに追加する必要があります。私が必要としているのは、type="Image" をクラス Image に関連付ける方法です。

私はすでにエンティティをゲームに追加するために使用するメソッドを持っています。私の問題は、文字列を型にして、そこから新しいエンティティをインスタンス化する方法にあります。

私がやろうとしているのは、文字列から型を返すことですが、それが可能かどうかはわかりません。C#でこれを行う方法はありますか、それとも間違った角度から攻撃していますか?

4

3 に答える 3

3

はい、C# 型修飾名を使用して、説明したとおりに行うことができます。

たとえば、修飾名System.Drawing.Imageは「System.Drawing.Image, System.Drawing」です。修飾名は、いくつかの部分で構成されています。私の例では[型名]、[アセンブリ名]です。( msdn の参考記事)

型を含むアセンブリがアプリ ドメインに読み込まれている限り (この場合、アセンブリは System.Drawing です)、次の操作を実行してインスタンス化できます。

var imageType = Type.GetType("System.Drawing.Image, System.Drawing");
System.Drawing.Image image = Activator.CreateInstance(imageType );
于 2013-01-07T22:10:25.613 に答える
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;

    }
}
于 2013-01-07T23:10:39.527 に答える
0

xml の型から他のリソースのアセンブリの具象型へのマッピングを保存してください。特に、独自の型の定義/拡張を開始する場合。

例えば

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

レイアウト ファイルに完全修飾名を入力すると、何かを変更したい場合にすぐに使用できます。

Type.GetType と Activator.CreateInstance を指摘する dtyron は、ナットとボルトの良いスタートを切ってくれました。

于 2013-01-07T22:32:52.833 に答える