The ASN.1 SEQUENCE type is converted to a C# class that inherits the Asn1Type run-time base class. Public member variables are generated for each of the elements defined in the SEQUENCE. Each of these member variables represents an object reference since all of the ASN.1 types are mapped to C# objects.
ASN.1 Production: |
<name> ::= SEQUENCE { <element1-name> <element1-type>, <element2-name> <element2-type>, ... } |
XSD Types: |
<xsd:sequence>, <xsd:all> |
Generated C# class: |
public class <name> : Asn1Type { public <type1> <element1-name> public <type2> <element2-name> ... public <name> () : base() { } public <name> (<type1> <arg1>, <type2> <arg2>, …) : base() { <element1-name> = <arg1>; <element2-name> = <arg2>; ... } public <name> (<basetype1> <arg1>, <basetype2> <arg2>, …) : base() { <element1-name> = new <type1> (<arg1>); <element2-name> = new <type2> (<arg2>); ... } private void Init () { … } public override void Decode () { … } public override int Encode () { … } public override void Print () { … } |
Notes:
The … notation used in the ASN.1 definition above does not represent the ASN.1 extensibility notation. It is used to show a continuation of the sequence elements.
The <type1>, <type2>, etc. items denote the equivalent C# types generated from the ASN.1 <element-type1>, <element-type2>, etc. definitions.
The public and private methods that are generated are shown without arguments or function bodies for brevity.
The compiler first generates a public member variable for each of the elements defined in the SEQUENCE. The decision was made to make these variables public to make them easier to populate for encoding. The alternative was to use protected or private variables with get/set methods for setting or examining the values. It was felt that this approach would be too cumbersome for setting values in deeply nested constructed types.
A default constructor is then generated followed by overloaded constructors for setting the element values. The first form is simply a direct mapping of each of the element types to a constructor argument. The second form only contains arguments for the required types in the SEQUENCE (i.e. OPTIONAL and DEFAULT elements are omitted). The third form uses the base type of each of the elements as the type for each argument. This makes it possible to construct a SEQUENCE or SET using literal variables instead of always having to create an object. Finally, another variant of this constructor with primitive types is generated for required elements only. It is possible that you will not see all of these variations in a given generated class. It depends on a) whether or not the SEQUENCE or SET contains optional items and b) whether or not it contains primitive data items.
For example, the following shows how a variable of a generated class containing two IA5String elements could be constructed:
v1 = new HelloWorld (“hello”, “world”);
Without this second form of constructor, the following would need to be done:
v1 = new HelloWorld (new Asn1IA5String(“hello”), new Asn1IA5String(“world”));
Also note that since all member variables are public, it is not necessary to use any of the argument-based constructors at all. A variable can be created using the default constructor and each of the elements populated directly.