2013-01-07 2 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는 이미지를 만들고 폼에 추가해야합니다. 내가 필요한 것은 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

Hmm this 일할 수도 있습니다. 새 개체를 목록에 추가 할 수 있어야합니다. 필드를 가질 필요가 없으므로 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; 

    } 
} 
관련 문제