public override int encode(IASN1TypesEncoder encoder, object obj, Stream stream, ElementInfo elementInfo)
        {
            Object result = null;
            ASN1ElementMetadata saveInfo = elementInfo.PreparedASN1ElementInfo;

            elementInfo.PreparedInfo = (valueFieldMeta);
            if (!CoderUtils.isNullField(valueField, elementInfo))
            {
                result = encoder.invokeGetterMethodForField(valueField, obj, elementInfo);
            }
            if (saveInfo != null)
            {
                if (!saveInfo.HasTag &&
                    elementInfo.hasPreparedASN1ElementInfo() &&
                    elementInfo.PreparedASN1ElementInfo.HasTag)
                {
                    ASN1ElementMetadata elData = new ASN1ElementMetadata(
                        saveInfo.Name,
                        saveInfo.IsOptional,
                        elementInfo.PreparedASN1ElementInfo.HasTag,
                        elementInfo.PreparedASN1ElementInfo.IsImplicitTag,
                        elementInfo.PreparedASN1ElementInfo.TagClass,
                        elementInfo.PreparedASN1ElementInfo.Tag,
                        saveInfo.HasDefaultValue
                        );
                    elementInfo.PreparedASN1ElementInfo = elData;
                }
                else
                {
                    elementInfo.PreparedASN1ElementInfo = (saveInfo);
                }
            }
            return(valueFieldMeta.TypeMetadata.encode(encoder, result, stream, elementInfo));
        }
        public override DecodedObject <object> decode(IASN1TypesDecoder decoder, DecodedObject <object> decodedTag, Type objectClass, ElementInfo elementInfo, Stream stream)
        {
            IASN1PreparedElementData saveInfo     = elementInfo.PreparedInfo;
            IASN1PreparedElement     instance     = (IASN1PreparedElement)elementInfo.PreparedInstance;
            ASN1ElementMetadata      saveElemInfo = elementInfo.PreparedASN1ElementInfo;

            elementInfo.PreparedInfo = (valueFieldMeta);

            if (saveElemInfo != null)
            {
                if (!saveElemInfo.HasTag &&
                    elementInfo.hasPreparedASN1ElementInfo() &&
                    elementInfo.PreparedASN1ElementInfo.HasTag)
                {
                    ASN1ElementMetadata elData = new ASN1ElementMetadata(
                        saveElemInfo.Name,
                        saveElemInfo.IsOptional,
                        elementInfo.PreparedASN1ElementInfo.HasTag,
                        elementInfo.PreparedASN1ElementInfo.IsImplicitTag,
                        elementInfo.PreparedASN1ElementInfo.TagClass,
                        elementInfo.PreparedASN1ElementInfo.Tag,
                        saveElemInfo.HasDefaultValue
                        );
                    elementInfo.PreparedASN1ElementInfo = elData;
                }
                else
                {
                    elementInfo.PreparedASN1ElementInfo = (saveElemInfo);
                }
            }
            DecodedObject <object> decodedResult =
                valueFieldMeta.TypeMetadata.decode(decoder, decodedTag, valueField.PropertyType, elementInfo, stream);

            if (decodedResult != null)
            {
                if (!CoderUtils.isNullField(valueField, elementInfo))
                {
                    decoder.invokeSetterMethodForField(valueField, instance, decodedResult.Value, elementInfo);
                }
            }
            elementInfo.PreparedInfo            = (saveInfo);
            elementInfo.PreparedInstance        = (instance);
            elementInfo.PreparedASN1ElementInfo = (saveElemInfo);

            if (decodedResult != null)
            {
                return(new DecodedObject <object>(instance, decodedResult.Size));
            }
            else
            {
                return(decodedResult);
            }
        }
        /*public ASN1PreparedElementData(Type parentClass, String propertyName)
        {
            try
            {
                PropertyInfo field = parentClass.GetProperty(propertyName);
                setupMetadata(field, field.PropertyType);
                setupAccessors(parentClass, field);
            }
            catch (Exception ex)
            {
                ex = null;
            }
        }*/
        private void setupMetadata(ICustomAttributeProvider annotated, Type objectClass)
        {
            if( CoderUtils.isAttributePresent<ASN1SequenceOf>(annotated) ) {
                typeMeta = new ASN1SequenceOfMetadata( CoderUtils.getAttribute<ASN1SequenceOf> (annotated),
                    objectClass,
                    annotated
                ) ;
            }
            else
            if( CoderUtils.isAttributePresent<ASN1Sequence>(annotated) ) {
                typeMeta = new ASN1SequenceMetadata( CoderUtils.getAttribute<ASN1Sequence> (annotated) ) ;
            }
            else
            if( CoderUtils.isAttributePresent<ASN1Choice>(annotated) ) {
                typeMeta = new ASN1ChoiceMetadata( CoderUtils.getAttribute<ASN1Choice> (annotated) ) ;
            }
            else
            if( CoderUtils.isAttributePresent<ASN1Enum>(annotated) ) {
                typeMeta = new ASN1EnumMetadata( CoderUtils.getAttribute<ASN1Enum> (annotated) ) ;
            }
            else
            if( CoderUtils.isAttributePresent<ASN1Boolean>(annotated) ) {
                typeMeta = new ASN1BooleanMetadata( CoderUtils.getAttribute<ASN1Boolean> (annotated) ) ;
            }
            else
            if( CoderUtils.isAttributePresent<ASN1Any>(annotated) ) {
                typeMeta = new ASN1AnyMetadata( CoderUtils.getAttribute<ASN1Any> (annotated) ) ;
            }
            else
            if( CoderUtils.isAttributePresent<ASN1Integer>(annotated) ) {
                typeMeta = new ASN1IntegerMetadata( CoderUtils.getAttribute<ASN1Integer> (annotated) ) ;
            }
            else
            if( CoderUtils.isAttributePresent<ASN1Real>(annotated) ) {
                typeMeta = new ASN1RealMetadata( CoderUtils.getAttribute<ASN1Real> (annotated) ) ;
            }
            else
            if( CoderUtils.isAttributePresent<ASN1OctetString>(annotated) ) {
                typeMeta = new ASN1OctetStringMetadata( CoderUtils.getAttribute<ASN1OctetString> (annotated) ) ;
            }
            else
            if (CoderUtils.isAttributePresent<ASN1BitString>(annotated) || objectClass.Equals(typeof(BitString)))
            {
                typeMeta = new ASN1BitStringMetadata ( CoderUtils.getAttribute<ASN1BitString> (annotated) ) ;
            }
            else
            if (CoderUtils.isAttributePresent<ASN1ObjectIdentifier>(annotated) || objectClass.Equals(typeof(ObjectIdentifier)))
            {
                typeMeta = new ASN1ObjectIdentifierMetadata(CoderUtils.getAttribute<ASN1ObjectIdentifier>(annotated));
            }
            else
            if( CoderUtils.isAttributePresent<ASN1String>(annotated) ) {
                typeMeta = new ASN1StringMetadata ( CoderUtils.getAttribute<ASN1String> (annotated) ) ;
            }
            else
            if( CoderUtils.isAttributePresent<ASN1Null>(annotated) ) {
                typeMeta = new ASN1NullMetadata ( CoderUtils.getAttribute<ASN1Null> (annotated) ) ;
            }
            else
            if( CoderUtils.isAttributePresent<ASN1BoxedType>(annotated) ) {
                typeMeta = new ASN1BoxedTypeMetadata ( objectClass, CoderUtils.getAttribute<ASN1BoxedType> (annotated) ) ;
            }
            else
            if( CoderUtils.isAttributePresent<ASN1Element>(annotated) ) {
                typeMeta = new ASN1ElementMetadata ( CoderUtils.getAttribute<ASN1Element> (annotated) ) ;
            }
            else
            if(objectClass.Equals(typeof(String))) {
                typeMeta = new ASN1StringMetadata( ) ;
            }
            else
            if(objectClass.Equals(typeof(int))) {
                typeMeta = new ASN1IntegerMetadata( ) ;
            }
            else
            if(objectClass.Equals(typeof(long))) {
                typeMeta = new ASN1IntegerMetadata( ) ;
            }
            else
            if(objectClass.Equals(typeof(double))) {
                typeMeta = new ASN1RealMetadata( ) ;
            }
            else
            if(objectClass.Equals(typeof(bool))) {
                typeMeta = new ASN1BooleanMetadata( ) ;
            }
            else
            if(objectClass.Equals(typeof(byte[]))) {
                typeMeta = new ASN1OctetStringMetadata( ) ;
            }

            if( CoderUtils.isAttributePresent<ASN1Element>(annotated) ) {
                asn1ElementInfo = new ASN1ElementMetadata(CoderUtils.getAttribute<ASN1Element>(annotated));
            }

            setupConstraint(annotated);
        }