internal static PropertyMapping Create(PropertyInfo prop, out IEnumerable<Type> referredTypes)        
        {
            if (prop == null) throw Error.ArgumentNull("prop");

            var foundTypes = new List<Type>();

            PropertyMapping result = new PropertyMapping();

#if (PORTABLE45 || NETCOREAPP1_1)
			var elementAttr = prop.GetCustomAttribute<FhirElementAttribute>();
#else
			var elementAttr = (FhirElementAttribute)Attribute.GetCustomAttribute(prop, typeof(FhirElementAttribute));
#endif
       
            result.Name = determinePropertyName(prop);
            result.ReturnType = prop.PropertyType;
            result.ElementType = result.ReturnType;

            result.InSummary = elementAttr != null ? elementAttr.InSummary : false;            
            result.Choice = elementAttr != null ? elementAttr.Choice : ChoiceType.None;

            if (elementAttr != null)
            {
                result.SerializationHint = elementAttr.XmlSerialization;
                result.Order = elementAttr.Order;
            }

            foundTypes.Add(result.ElementType);

            result.IsCollection = ReflectionHelper.IsTypedCollection(prop.PropertyType) && !prop.PropertyType.IsArray;

            // Get to the actual (native) type representing this element
            if (result.IsCollection) result.ElementType = ReflectionHelper.GetCollectionItemType(prop.PropertyType);
            if (ReflectionHelper.IsNullableType(result.ElementType)) result.ElementType = ReflectionHelper.GetNullableArgument(result.ElementType);
            result.IsPrimitive = isAllowedNativeTypeForDataTypeValue(result.ElementType);

            // Check wether this property represents a native .NET type
            // marked to receive the class' primitive value in the fhir serialization
            // (e.g. the value from the Xml 'value' attribute or the Json primitive member value)
            if(result.IsPrimitive) result.RepresentsValueElement = isPrimitiveValueElement(prop);

            referredTypes = foundTypes;

            // May need to generate getters/setters using pre-compiled expression trees for performance.
            // See http://weblogs.asp.net/marianor/archive/2009/04/10/using-expression-trees-to-get-property-getter-and-setters.aspx
            result._getter = instance => prop.GetValue(instance, null);
            result._setter = (instance,value) => prop.SetValue(instance, value, null);
            
            return result;
        }
        internal static PropertyMapping Create(PropertyInfo prop, out IEnumerable <Type> referredTypes)
        {
            if (prop == null)
            {
                throw Error.ArgumentNull(nameof(prop));
            }

            var foundTypes = new List <Type>();

            PropertyMapping result = new PropertyMapping();

            var elementAttr     = prop.GetCustomAttribute <FhirElementAttribute>();
            var cardinalityAttr = prop.GetCustomAttribute <Validation.CardinalityAttribute>();
            var allowedTypes    = prop.GetCustomAttribute <Validation.AllowedTypesAttribute>();

            result.Name             = determinePropertyName(prop);
            result.ImplementingType = prop.PropertyType;

            result.InSummary          = elementAttr?.InSummary ?? false;
            result.IsMandatoryElement = cardinalityAttr != null ? cardinalityAttr.Min > 0 : false;
            result.Choice             = elementAttr?.Choice ?? ChoiceType.None;

            if (elementAttr != null)
            {
                result.SerializationHint = elementAttr.XmlSerialization;
                result.Order             = elementAttr.Order;
            }

            result.IsCollection = ReflectionHelper.IsTypedCollection(prop.PropertyType) && !prop.PropertyType.IsArray;

            // Get to the actual (native) type representing this element
            if (result.IsCollection)
            {
                result.ImplementingType = ReflectionHelper.GetCollectionItemType(prop.PropertyType);
            }
            if (ReflectionHelper.IsNullableType(result.ImplementingType))
            {
                result.ImplementingType = ReflectionHelper.GetNullableArgument(result.ImplementingType);
            }
            result.IsPrimitive = isAllowedNativeTypeForDataTypeValue(result.ImplementingType);

            result.IsBackboneElement = result.ImplementingType.CanBeTreatedAsType(typeof(IBackboneElement));
            foundTypes.Add(result.ImplementingType);

            // Derive the C# type that represents which types are allowed for this element.
            // This may differ from the ImplementingType in several ways:
            // * for a choice, ImplementingType = Any, but FhirType[] contains the possible choices
            // * some elements (e.g. Extension.url) have ImplementingType = string, but FhirType = FhirUri, etc.
            if (allowedTypes != null)
            {
                result.FhirType = allowedTypes.Types;
            }
            else if (elementAttr?.TypeRedirect != null)
            {
                result.FhirType = new[] { elementAttr.TypeRedirect }
            }
            ;
            else
            {
                result.FhirType = new[] { result.ImplementingType }
            };

            // Check wether this property represents a native .NET type
            // marked to receive the class' primitive value in the fhir serialization
            // (e.g. the value from the Xml 'value' attribute or the Json primitive member value)
            if (result.IsPrimitive)
            {
                result.RepresentsValueElement = isPrimitiveValueElement(prop);
            }

            referredTypes = foundTypes;

#if USE_CODE_GEN
            result._getter = prop.GetValueGetter();
            result._setter = prop.GetValueSetter();
#else
            result._getter = instance => prop.GetValue(instance, null);
            result._setter = (instance, value) => prop.SetValue(instance, value, null);
#endif
            return(result);
        }
        //private static void checkMutualExclusiveAttributes(Type type)
        //{
        //    if (ClassMapping.IsFhirResource(type) && ClassMapping.IsFhirComplexType(type))
        //        throw Error.Argument("type", "Type {0} cannot be both a Resource and a Complex datatype", type);
        //    if (ClassMapping.IsFhirResource(type) && ClassMapping.IsFhirPrimitive(type))
        //        throw Error.Argument("type", "Type {0} cannot be both a Resource and a Primitive datatype", type);
        //    if (ClassMapping.IsFhirComplexType(type) && ClassMapping.IsFhirPrimitive(type))
        //        throw Error.Argument("type", "Type {0} cannot be both a Complex and a Primitive datatype", type);
        //}


        //private static object invokeEnumParser(string input, Type enumType)
        //{
        //    object result = null;
        //    bool success = EnumHelper.TryParseEnum(input, enumType, out result);

        //    if (!success)
        //        throw Error.InvalidOperation("Parsing of enum failed");

        //    return result;
        //}


        private static string getProfile(Type type)
        {
            var attr = ReflectionHelper.GetAttribute <FhirTypeAttribute>(type);

            return(attr != null ? attr.Profile : null);
        }