/// <summary>
        /// Create a new instance of FieldMetaData with a given MemberInfo.
        /// </summary>
        /// <param name="outRef">Indicates the reference of the out object that hold this constraint.</param>
        /// <param name="info"></param>
        /// <remarks>
        /// AttachedTag, Constraint will be set automatically by reflection.
        /// </remarks>
        protected Asn1ConstraintedFieldMetadata(Asn1Object outRef, MemberInfo info)
        {
            OutReference = outRef;
            MemberInfo = info;

            //Get AttachedTag
            AttachedTag = null;
            var attrs = MemberInfo.GetCustomAttributes(typeof(Asn1Tag), true);
            if (attrs.Length != 0)
            {
                //Only the first tag is valid.
                Asn1Tag tag = attrs[0] as Asn1Tag;
                if (tag.TagType != Asn1TagType.Context && tag.TagType != Asn1TagType.Application)
                {
                    throw new Asn1UserDefinedTypeInconsistent(ExceptionMessages.UserDefinedTypeInconsistent
                        + " Only Context-Specific tag and Application tag are allowed.");
                }
                AttachedTag = tag;
            }

            //Get Constraint
            Constraint = GetConstraints();
        }
 /// <summary>
 /// Encodes a tag to the buffer.
 /// </summary>
 /// <param name="buffer"></param>
 /// <param name="tag"></param>
 /// <returns>The length of the encoding result.</returns>
 /// <remarks>Override this method in a user-defined class only if the procedure is not applicable in some special scenarios.</remarks>
 protected virtual int TagBerEncode(IAsn1BerEncodingBuffer buffer, Asn1Tag tag)
 {
     return Asn1StandardProcedure.TagBerEncode(buffer, tag);
 }
 /// <summary>
 /// Decodes a tag from the buffer.
 /// </summary>
 /// <param name="buffer"></param>
 /// <param name="tag"></param>
 /// <returns>The number of the bytes consumed in the buffer to decode the tag.</returns>
 /// <remarks>Override this method in a user-defined class only if the procedure is not applicable in some special scenarios.</remarks>
 protected virtual int TagBerDecode(IAsn1DecodingBuffer buffer, out Asn1Tag tag)
 {
     return Asn1StandardProcedure.TagBerDecode(buffer, out tag);
 }
 /// <summary>
 /// Encodes a tag to the buffer.
 /// </summary>
 /// <param name="buffer"></param>
 /// <param name="tag"></param>
 /// <returns>The length of the encoding result.</returns>
 public static int TagBerEncode(IAsn1BerEncodingBuffer buffer, Asn1Tag tag)
 {
     //Ref. X.690: 8.1.2.2, there are four kinds of tags
     byte prefix = 0;
     switch (tag.TagType)
     {
         case Asn1TagType.Universal:
             {
                 prefix = 0;//00
             } break;
         case Asn1TagType.Application:
             {
                 prefix = 1;//01
             } break;
         case Asn1TagType.Context:
             {
                 prefix = 2;//10
             } break;
         case Asn1TagType.Private:
             {
                 prefix = 3;//11
                 //Ref. X.680: G.2.12.4
                 throw new Asn1UnreachableExcpetion(ExceptionMessages.Unreachable);
             };
     }
     prefix <<= 6;
     if (tag.EncodingWay == EncodingWay.Constructed)
     {
         prefix |= (1 << 5);//Set the sixth bit to 1 if it is encoded in constructed way. Ref. X.690: 8.1.2.3
     }
     if (tag.TagValue <= 30)//Use one byte to store the encoding result
     //Ref. X.690: 8.1.2.3
     {
         prefix |= (byte)tag.TagValue;
         buffer.WriteByte(prefix);
         return 1;
     }
     else//Use more than one bytes to store.
     {
         //Ref. X.690: 8.1.2.4.3
         throw new NotImplementedException("Case tag > 30 is not implemented. Check X.690: 8.1.2.4.3.");
     }
 }
 /// <summary>
 /// Decodes a tag from the buffer.
 /// </summary>
 /// <param name="buffer"></param>
 /// <param name="tag"></param>
 /// <returns>The number of the bytes consumed in the buffer to decode the tag.</returns>
 public static int TagBerDecode(IAsn1DecodingBuffer buffer, out Asn1Tag tag)
 {
     byte prefix = buffer.ReadByte();
     int firstTwoBits = (prefix >> 6);
     Asn1TagType tagType = Asn1TagType.Private;
     long tagValue;
     switch (firstTwoBits)
     {
         case 0:
             {
                 tagType = Asn1TagType.Universal;
             } break;
         case 1:
             {
                 tagType = Asn1TagType.Application;
             } break;
         case 2:
             {
                 tagType = Asn1TagType.Context;
             } break;
         case 3:
             {
                 throw new NotImplementedException(ExceptionMessages.Unreachable);
             };
     }
     tagValue = prefix & ((byte)(1 << 5) - 1);
     if (tagValue <= 30)
     {
         tag = new Asn1Tag(tagType, tagValue);
         if ((prefix & (1 << 5)) != 0)
         {
             tag.EncodingWay = EncodingWay.Constructed;
         }
         else
         {
             tag.EncodingWay = EncodingWay.Primitive;
         }
         return 1;
     }
     else
     {
         throw new NotImplementedException("Case tag > 30 is not implemented. Check X.690: 8.1.2.4.3.");
     }
 }
 public override int BerEncode(IAsn1BerEncodingBuffer buffer, bool explicitTag = true)
 {
     int allLen = 0;
     Asn1Tag contextTag;
     switch (SelectedChoice)
     {
         case 0:
             allLen += field0.BerEncodeWithoutUnisersalTag(buffer);
             contextTag = new Asn1Tag(Asn1TagType.Context, 0) { EncodingWay = EncodingWay.Primitive };
             allLen += TagBerEncode(buffer, contextTag);
             break;
         case 1:
             allLen += field1.BerEncodeWithoutUnisersalTag(buffer);
             contextTag = new Asn1Tag(Asn1TagType.Context, 3) { EncodingWay = EncodingWay.Constructed };
             allLen += TagBerEncode(buffer, contextTag);
             break;
         case 2:
             allLen += field2.BerEncodeWithoutUnisersalTag(buffer);
             contextTag = new Asn1Tag(Asn1TagType.Context, 9) { EncodingWay = EncodingWay.Primitive };
             allLen += TagBerEncode(buffer, contextTag);
             break;
         case 3:
             allLen += field3.BerEncodeWithoutUnisersalTag(buffer);
             contextTag = new Asn1Tag(Asn1TagType.Context, 10) { EncodingWay = EncodingWay.Primitive };
             allLen += TagBerEncode(buffer, contextTag);
             break;
         case 4:
             allLen += field4.BerEncodeWithoutUnisersalTag(buffer);
             contextTag = new Asn1Tag(Asn1TagType.Context, 11) { EncodingWay = EncodingWay.Primitive };
             allLen += TagBerEncode(buffer, contextTag);
             break;
         default:
             throw new Asn1ConstraintsNotSatisfied(ExceptionMessages.InvalidChoiceIndex + " AuthenticationChoice");
     }
     return allLen;
 }