Example #1
0
        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>();

            result.Name        = determinePropertyName(prop);
            result.ReturnType  = prop.PropertyType;
            result.ElementType = result.ReturnType;

            result.InSummary          = elementAttr != null ? elementAttr.InSummary : false;
            result.IsMandatoryElement = cardinalityAttr != null ? cardinalityAttr.Min > 0 : 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);
        }
        //public Type GetChoiceType(string choiceSuffix)
        //{
        //    string suffix = choiceSuffix.ToUpperInvariant();

        //    if(!HasChoices) return null;

        //    return _choices
        //                .Where(cattr => cattr.TypeName.ToUpperInvariant() == suffix)
        //                .Select(cattr => cattr.Type)
        //                .FirstOrDefault(); 
        //}
   

        private static bool isAllowedNativeTypeForDataTypeValue(Type type)
        {
            // Special case, allow Nullable<enum>
            if (ReflectionHelper.IsNullableType(type))
                type = ReflectionHelper.GetNullableArgument(type);

            return type.IsEnum() ||
                    PrimitiveTypeConverter.CanConvert(type);
        }
        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);
        }