/// <summary>
 /// Initializes a new instance of the Asn1Integer class with a given value and bounds.
 /// </summary>
 /// <param name="val"></param>
 /// <param name="min"></param>
 /// <param name="max"></param>
 protected internal Asn1Integer(long? val, long? min, long? max)
 {
     Value = val;
     if (Constraints == null)
     {
         Constraints = new Asn1IntegerBound();
         if (min != null)
         {
             Constraints.Min = (long)min;
         }
         if (max != null)
         {
             Constraints.Max = (long)max;
         }
     }
 }
        /// <summary>
        /// Initializes a new instance of the Asn1Integer class with a given value.
        /// </summary>
        /// <param name="val"></param>
        public Asn1Integer(long? val)
        {
            Value = val;
            Constraints = null;

            //Gets the upper and lower bound for the structure.
            object[] allAttributes = GetType().GetCustomAttributes(true);
            foreach (object o in allAttributes)
            {
                if (o is Asn1IntegerBound)
                {
                    Constraints = o as Asn1IntegerBound;
                    break;
                }
            }
        }
        /// <summary>
        /// Initializes a new instance of the Asn1Enumerated class with a given value. 
        /// </summary>
        /// <param name="val"></param>
        protected Asn1Enumerated(long? val)
            : base(val)
        {
            //Get all the allowed values by checking the Asn1EnumeratedElement attribute on each member.

            //TODO: initiate allowedValues once for each derived type, not each instance.
            allowedValues = new List<long?>();

            MemberInfo[] mis = this.GetType().GetMembers(
                BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);

            foreach (var mi in mis)
            {
                if (mi.IsDefined(typeof(Asn1EnumeratedElement), true))
                {
                    object o = null;
                    if (mi.MemberType == MemberTypes.Property)
                    {
                        PropertyInfo pi = this.GetType().GetProperty(mi.Name);
                        o = pi.GetValue(this, null);
                    }
                    else if (mi.MemberType == MemberTypes.Field)
                    {
                        FieldInfo fi = this.GetType().GetField(mi.Name);
                        o = fi.GetValue(this);
                    }
                    else
                    {
                        //Unreachable. Ensured by the AttributeUsage of Asn1EnumeratedElement.
                        throw new Asn1UserDefinedTypeInconsistent(ExceptionMessages.UserDefinedTypeInconsistent
                            + " Asn1Field property could only be used in properties or fields.");
                    }

                    if (o == null)
                    {
                        throw new Asn1UserDefinedTypeInconsistent(ExceptionMessages.UserDefinedTypeInconsistent
                            + " " + mi.Name + " in class " + this.GetType().Name + " can't be null.");
                    }
                    long allowedValue = Convert.ToInt64(o);
                    if (allowedValues.Contains(allowedValue))
                    {
                        throw new Asn1UserDefinedTypeInconsistent(ExceptionMessages.UserDefinedTypeInconsistent
                            + " Deplicated indices for " + mi.Name + " in class " + this.GetType().Name + ".");
                    }
                    allowedValues.Add(allowedValue);
                }
            }

            if (allowedValues.Count == 0)
            {
                throw new Asn1UserDefinedTypeInconsistent(ExceptionMessages.UserDefinedTypeInconsistent
                    + String.Format(" There must be at least one enumaration for {0}.", GetType()));
            }
            allowedValues.Sort();

            Constraints = new Asn1IntegerBound() { Min = 0, Max = allowedValues.Count - 1 };
        }