2009-10-28 3 views
7

다음 XML 예제에서 우리는 Type1과 Type2 사이의 선택 안함 수의 시퀀스를 포함하는 루트를 정의하는 스키마를 상상할 수 있습니다.선택 순서대로 순서 보존 (LINQ to XSD)

<Root> 
    <Type1 /> 
    <Type2 /> 
    <Type2 /> 
    <Type1 /> 
</Root> 

XSD.exe 도구에서 마이그레이션을 테스트하고 있습니다. 유형 안전성에 많은 불편 함이 있지만 테스트 도구입니다. 이 경우 XSD 도구는 Root 내에 System.Object 유형의 배열을 만들고 거기에 어떤 유형의 객체 (Type1 또는 Type2)가 있는지 알아 내야합니다. 완전히 우아하지는 않지만 적어도 당신은 질서를 유지합니다.

문제는 LINQ to XSD가 개체를 만들 때 루트가 Type1 및 Type2의 두 가지 독립 목록을 가진 것으로 정의하는 경우입니다. 이것은 타입 안전하다는 점에서 훌륭하지만, 이제는 엘리먼트의 순서를 잃어 버리는 것처럼 보입니다. 내가 codeplex에있는 소스에서 XSD에 LINQ를 만들었습니다.

LINQ to XSD를 사용하면 어떻게 이러한 요소의 순서를 유지할 수 있습니까?

+3

글쎄, 이미 두 가지 옵션 만 제시했습니다. 순서를 유지하는 약한 형식의 컬렉션을 얻거나 형식마다 강력한 형식의 컬렉션을 얻습니다. XML을 전혀 사용하지 않는 척하십시오. 여러 유형의 강력한 형식화 된 컬렉션이 하나있는 순수 코드 객체를 작성하는 방법은 무엇입니까? –

+0

제 질문은 Linq to XSD를 사용하여이 시나리오에서 요소의 순서를 유지하는 방법입니다. 나는 그들이 System.Object (또는 공통점이있는 부모)가 될 필요가있는 혼합 유형의 콜렉션을 가지고 있다는 것을 알고있다. 나는이 시나리오에서 XSD에 Linq를 사용하여 순서를 유지하기 위해 강력하게 형식화 된 객체를 포기할 의향이 있습니다. 나는 그렇게 할 수있는 방법이 있기를 바랬다. XSD.exe보다 많은 장점을 가지고 있기 때문에 실제로 사용하고 싶지만 Linq를 XSD에 사용할 수는 없으므로 사용 사례에서는 문제가 발생합니다. – Philip

+6

상속을 사용하면이 작업을 수행 할 수 있습니다. Type1과 Type2에 공통 기본 클래스가있는 경우 IList 을 가질 수 있습니다. 이제 강하게 입력 된 단일 목록이 있으며 주문이 보존됩니다.목록을 반복 할 때 현재 객체의 유형을 확인하십시오. 당신이 대답처럼 의 foreach {(엘은 타입 1 인) 경우 (엘이 타입 2 인) 다른 경우 ... } (요소 baseType 여기서 엘) –

답변

2

선택 사항 주위에 래퍼를 만드는 방법은 어떻습니까? 이 같은 액세스 유형을 제한 :

class Choice 
{ 
    private object _value; 

    public ChoiceEnum CurrentType { get; private set; } 

    public Type1 Type1Value 
    { 
     get { return (Type1) _value; } 
     set { _value = value; CurrentType = ChoiceEnum.Type1; } 
    } 

    public Type2 Type2Value 
    { 
     get { return (Type2) _value; } 
     set { _value = value; CurrentType = ChoiceEnum.Type2; } 
    } 
} 

이 단순화 된 버전이며, 더 많은 유효성 검사를 추가해야합니다 (_value가 올바른 형태의 경우는, _value의 현재 유형 등 것입니다).

var q1 = from v in root.Sequence 
     where v.CurrentType == ChoiceEnum.Type1 
     select v.Type1; 

을 또는 당신은 쿼리를 감싸 루트의 메소드를 만들 수 있습니다

다음, 당신은 LINQ로를 필터링 할 수 있습니다.

+0

좋습니다. 이것은 제대로 작동하지만 불행한 XSD 자체의 디자인을 결정합니다 (예 : 업계 표준 스키마). 우리 팀과 함께 작업하는 많은 스키마가 우리에 의해 만들어 졌기 때문에이 기술을 사용할 수 있습니다. – Philip

1

Linq2Xsd는 xsd : choice 요소가있을 때만 시퀀스를 트립합니다.

다행히도 Amazon XSD에 대한 xsd : 선택 항목을 제거 할 수있었습니다. x32에 대해 ToString()에 올바르게 보존 된 시퀀스를 허용하는 MerchantOrderID를 사용하고있었습니다.

  <xsd:choice>        <--- removed line 
       <xsd:element ref="AmazonOrderID"/> 
       <xsd:element ref="MerchantOrderID"/> <--- removed line 
      </xsd:choice>        <--- removed line 

      <xsd:element name="ActionType" minOccurs="0" maxOccurs="1"> 
       <xsd:simpleType> 
        <xsd:restriction base="xsd:string"> 
         <xsd:enumeration value="Refund"/> 
         <xsd:enumeration value="Cancel"/> 
        </xsd:restriction> 
       </xsd:simpleType> 
      </xsd:element> 

생성 된 코드는 올바르게 순서

contentModel = new SequenceContentModelEntity(
       new NamedContentModelEntity(XName.Get("AmazonOrderID", "")), 
       new NamedContentModelEntity(XName.Get("ActionType", "")), 
       new NamedContentModelEntity(XName.Get("CODCollectionMethod", "")), 
       new NamedContentModelEntity(XName.Get("AdjustedItem", ""))); 

또한 그것을 youself를 서브 클래스로 수동으로이 작업을 수행 할 수 있습니다을 유지 생성자에서이 문제를 가지고 있지만 난 이것이 xsd : choice로 어떻게 작동하는지 확신 할 수 없습니다. 이것은 described here이지만 테스트하지 않았습니다.