views:

1491

answers:

3

I am running a custom application that imports WSDLs and generates C# source code, using WSDLImporter class to read in contracts.

XSD sequence types are translated into native arrays. What options can I set in order to be able to generate custom collection types?

Schema:

<xs:complexType name="getAllSourcesResponse">
    <xs:sequence>
        <xs:element maxOccurs="unbounded" minOccurs="0" 
            name="return" type="tns:Source"/>
    </xs:sequence>
</xs:complexType>

becomes code:

public partial class getAllSourcesResponse
{
    [System.Xml.Serialization.XmlElementAttribute("return",
        Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public PaymentSource[] @return;

    public getAllSourcesResponse()
    {
    }

    public getAllSourcesResponse(Source[] @return)
    {
        this.@return = @return;
    }
}

I looked into SvcUtil.exe code, it appears to do the following, but it does not seem to make any difference in what code my application produces.

WsdlImporter importer = ... 

XsdDataContractImporter contractImporter = 
    new XsdDataContractImporter(codeCompileUnit); 

ImportOptions importOptions = new ImportOptions();
importOptions.ReferencedCollectionTypes.Add(
    typeof(System.Collections.Generic.IList<>)); 

contractImporter.Options = importOptions; 

importer.State.Add(typeof(XsdDataContractImporter), contractImporter);
A: 

Is WCF an option?

Ian P
no, I have to use the provided infrastructure
A: 

First, I believe you need to indicate a collection implementation, not just the interface, so that means List<T> instead of IList<T> (although you can certainly try it with the interface).

Second, you need to specify the type parameter T:

ImportOptions importOptions = new ImportOptions();

importOptions.ReferencedCollectionTypes.Add(
    typeof(System.Collections.Generic.List<getAllSourcesResponse>));

As it was, you were passing the open generic type, which will not match with anything when the importer is trying to resolve the collection.

casperOne
The tool that's doing the conversion does not know about the types used in WSDLs. I can not specify "List<getAllSourcesResponse>" because getAllSourcesResponse is not a valid type or namespace, it causes a compile error.
I also tried "System.Collections.Generic.List<string>", but I still get "string[] " in the generated code, instead of "List<string>"
@janya: Well, why not get the schema for the getAllSourcesResponse ^first^ and get the type representation of that, and then import the contract definition?
casperOne
@casperOne: true enough, I'll do that, thank you. Any ideas why adding List<string> to the ReferencedCollectionTypes still gets string[] in generated code?
@janya: Because it can't match a string type to the schema definition. If it was a sequence of string elements, then it would be used as a string, but its a sequence of getAllSourcesResponse elements.
casperOne
@casperOne: how do I get a type representation from the imported schema?
A: 

@CasperOne, this schema snippet

<xs:complexType name="getClassesForPackageResponse">
     <xs:sequence>
         <xs:element maxOccurs="unbounded" minOccurs="0" name="return" type="xs:string"/>
     </xs:sequence>
 </xs:complexType>

generates a string[] type:

public partial class getClassesForPackageResponse
{
    public string[] @return;
    public getClassesForPackageResponse() {}

    public getClassesForPackageResponse(string[] @return)
    {    this.@return = @return;    }
}

This does not cause string collection to use List:

ImportOptions importOptions = new ImportOptions();
importOptions.ReferencedCollectionTypes.Add(
    typeof(System.Collections.Generic.List<string>));