/// <summary>
        ///     Bind to the given model type
        /// </summary>
        /// <param name="context">Current context</param>
        /// <param name="modelType">Model type to bind to</param>
        /// <param name="instance">Optional existing instance</param>
        /// <param name="configuration">The <see cref="BindingConfig" /> that should be applied during binding.</param>
        /// <param name="blackList">Blacklisted property names</param>
        /// <returns>Bound model</returns>
        public object Bind(NancyContext context, Type modelType, object instance, BindingConfig configuration,
            params string[] blackList)
        {
            Type genericType = null;
            if (modelType.IsArray() || modelType.IsCollection() || modelType.IsEnumerable())
            {
                //make sure it has a generic type
                if (modelType.IsGenericType())
                {
                    genericType = modelType.GetGenericArguments().FirstOrDefault();
                }
                else
                {
                    var implementingIEnumerableType =
                        modelType.GetInterfaces().Where(i => i.IsGenericType()).FirstOrDefault(
                            i => i.GetGenericTypeDefinition() == typeof (IEnumerable<>));
                    genericType = implementingIEnumerableType == null ? null : implementingIEnumerableType.GetGenericArguments().FirstOrDefault();
                }

                if (genericType == null)
                {
                    throw new ArgumentException("When modelType is an enumerable it must specify the type", "modelType");
                }
            }

            var bindingContext =
                CreateBindingContext(context, modelType, instance, configuration, blackList, genericType);

            var bodyDeserializedModel = DeserializeRequestBody(bindingContext);

            return (instance as IEnumerable<string>) ?? bodyDeserializedModel;
        }
Example #2
0
        /// <summary>
        /// Convert the string representation to the destination type
        /// </summary>
        /// <param name="input">Input string</param>
        /// <param name="destinationType">Destination type</param>
        /// <param name="context">Current context</param>
        /// <returns>Converted object of the destination type</returns>
        public object Convert(string input, Type destinationType, BindingContext context)
        {
            if (string.IsNullOrEmpty(input))
            {
                return null;
            }

            var items = input.Split(',');

            // Strategy, schmategy ;-)
            if (destinationType.IsCollection())
            {
                return this.ConvertCollection(items, destinationType, context);
            }

            if (destinationType.IsArray())
            {
                return this.ConvertArray(items, destinationType, context);
            }

            if (destinationType.IsEnumerable())
            {
                return this.ConvertEnumerable(items, destinationType, context);
            }

            return null;
        }
        /// <summary>
        /// Convert the string representation to the destination type
        /// </summary>
        /// <param name="input">Input string</param>
        /// <param name="destinationType">Destination type</param>
        /// <param name="context">Current context</param>
        /// <returns>Converted object of the destination type</returns>
        public object Convert(string input, Type destinationType, BindingContext context)
        {
            // TODO - Lots of reflection in here, should probably cache the methodinfos
            if (string.IsNullOrEmpty(input))
            {
                return null;
            }

            var items = input.Split(',');

            // Strategy, schmategy ;-)
            if (destinationType.IsCollection())
            {
                return this.ConvertCollection(items, destinationType, context);
            }

            if (destinationType.IsArray())
            {
                return this.ConvertArray(items, destinationType, context);
            }

            if (destinationType.IsEnumerable())
            {
                return this.ConvertEnumerable(items, destinationType, context);
            }

            return null;
        }
Example #4
0
        /// <summary>
        /// Bind to the given model type
        /// </summary>
        /// <param name="context">Current context</param>
        /// <param name="modelType">Model type to bind to</param>
        /// <param name="instance">Optional existing instance</param>
        /// <param name="configuration">The <see cref="BindingConfig"/> that should be applied during binding.</param>
        /// <param name="blackList">Blacklisted property names</param>
        /// <returns>Bound model</returns>
        public object Bind(NancyContext context, Type modelType, object instance, BindingConfig configuration, params string[] blackList)
        {
            Type genericType = null;
            if (modelType.IsArray() || modelType.IsCollection() || modelType.IsEnumerable())
            {
                //make sure it has a generic type
                if (modelType.IsGenericType())
                {
                    genericType = modelType.GetGenericArguments().FirstOrDefault();
                }
                else
                {
                    var ienumerable =
                        modelType.GetInterfaces().Where(i => i.IsGenericType()).FirstOrDefault(
                            i => i.GetGenericTypeDefinition() == typeof(IEnumerable<>));
                    genericType = ienumerable == null ? null : ienumerable.GetGenericArguments().FirstOrDefault();
                }

                if (genericType == null)
                {
                    throw new ArgumentException("when modeltype is an enumerble it must specify the type", "modelType");
                }
            }

            var bindingContext =
                this.CreateBindingContext(context, modelType, instance, configuration, blackList, genericType);

            var bodyDeserializedModel = this.DeserializeRequestBody(bindingContext);

            if (bodyDeserializedModel != null)
            {
                UpdateModelWithDeserializedModel(bodyDeserializedModel, bindingContext);
            }

            var bindingExceptions = new List<PropertyBindingException>();

            if (!bindingContext.Configuration.BodyOnly)
            {
                if (bindingContext.DestinationType.IsCollection() || bindingContext.DestinationType.IsArray() ||
                    bindingContext.DestinationType.IsEnumerable())
                {
                    var loopCount = GetBindingListInstanceCount(context);
                    var model = (IList)bindingContext.Model;
                    for (var i = 0; i < loopCount; i++)
                    {
                        object genericinstance;
                        if (model.Count > i)
                        {
                            genericinstance = model[i];
                        }
                        else
                        {
                            genericinstance = Activator.CreateInstance(bindingContext.GenericType);
                            model.Add(genericinstance);
                        }

                        foreach (var modelProperty in bindingContext.ValidModelProperties)
                        {
                            var existingCollectionValue = modelProperty.GetValue(genericinstance, null);

                            var collectionStringValue = GetValue(modelProperty.Name, bindingContext, i);

                            if (BindingValueIsValid(collectionStringValue, existingCollectionValue, modelProperty,
                                                    bindingContext))
                            {
                                try
                                {
                                    BindProperty(modelProperty, collectionStringValue, bindingContext, genericinstance);
                                }
                                catch (PropertyBindingException ex)
                                {
                                    bindingExceptions.Add(ex);
                                }
                            }
                        }
                    }
                }
                else
                {
                    foreach (var modelProperty in bindingContext.ValidModelProperties)
                    {
                        var existingValue = modelProperty.GetValue(bindingContext.Model, null);

                        var stringValue = GetValue(modelProperty.Name, bindingContext);

                        if (BindingValueIsValid(stringValue, existingValue, modelProperty, bindingContext))
                        {
                            try
                            {
                                BindProperty(modelProperty, stringValue, bindingContext);
                            }
                            catch (PropertyBindingException ex)
                            {
                                bindingExceptions.Add(ex);
                            }
                        }
                    }
                }

                if (bindingExceptions.Any())
                {
                    throw new ModelBindingException(modelType, bindingExceptions);
                }
            }

            if (modelType.IsArray())
            {
                var generictoArrayMethod = toArrayMethodInfo.MakeGenericMethod(new[] { genericType });
                return generictoArrayMethod.Invoke(null, new[] { bindingContext.Model });
            }
            return bindingContext.Model;
        }
Example #5
0
        private static object CreateModel(Type modelType, Type genericType, object instance)
        {
            if (modelType.IsArray() || modelType.IsCollection() || modelType.IsEnumerable())
            {
                //make sure instance has a Add method. Otherwise call `.ToList`
                if (instance != null && modelType.IsInstanceOfType(instance))
                {
                    var addMethod = modelType.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance);
                    if (addMethod != null)
                    {
                        return instance;
                    }
                    var genericMethod = toListMethodInfo.MakeGenericMethod(genericType);
                    return genericMethod.Invoke(null, new[] { instance });
                }

                //else just make a list
                var listType = typeof(List<>).MakeGenericType(genericType);
                return Activator.CreateInstance(listType);
            }

            if (instance == null)
            {
                return Activator.CreateInstance(modelType);
            }

            return !modelType.IsInstanceOfType(instance) ?
                Activator.CreateInstance(modelType) :
                instance;
        }
Example #6
0
 /// <summary>
 /// Whether the converter can convert to the destination type
 /// </summary>
 /// <param name="destinationType">Destination type</param>
 /// <param name="context">The current binding context</param>
 /// <returns>True if conversion supported, false otherwise</returns>
 public bool CanConvertTo(Type destinationType, BindingContext context)
 {
     return destinationType.IsCollection() || destinationType.IsEnumerable() || destinationType.IsArray();
 }
Example #7
0
        /// <summary>
        /// Bind to the given model type
        /// </summary>
        /// <param name="obj">object to be converted into a model</param>
        /// <param name="modelType">Model type to bind to</param>
        /// <param name="blackList">Blacklisted binding property names</param>
        /// <returns>Bound model</returns>
        public virtual object Bind(object obj, Type modelType)
        {
            if(obj == null)
            {
                return null;
            }

            Type genericType = null;
            if (modelType.IsCollectionOrArray())
            {
                //make sure it has a generic type
                if (modelType.GetTypeInfo().IsGenericType)
                {
                    genericType = modelType.GetGenericArguments().FirstOrDefault();
                }
                else
                {
                    var ienumerable = modelType.GetInterfaces().Where(i => i.GetTypeInfo().IsGenericType).FirstOrDefault(i => i.GetGenericTypeDefinition() == typeof(IEnumerable<>));
                    genericType = ienumerable == null ? null : ienumerable.GetGenericArguments().FirstOrDefault();
                }

                if (genericType == null)
                {
                    throw new ArgumentException("When modelType is an enumerable it must specify the type.", "modelType");
                }
            }

            var bindingContext = this.CreateBindingContext(obj, modelType, genericType);

            if (bindingContext.DestinationType.IsCollectionOrArray())
            {
                var model = (IList)bindingContext.Model;
                var collection = obj as ICollection;

                if(collection == null)
                {
                    return null;
                }

                for (var i = 0; i < collection.Count; i++)
                {
                    var val = GetValue(bindingContext, i);

                    if (val != null)
                    {
                        if (val.GetType() == typeof(Dictionary<string, object>))
                        {
                            var subModel = Bind(val, genericType);
                            model.Add(subModel);
                        }
                        else
                        {
                            model.Add(val);
                        }
                    }
                }
            }
            else
            {
                foreach (var modelProperty in bindingContext.ValidModelBindingMembers)
                {
                    var val = GetValue(modelProperty.Name, bindingContext);

                    if (val != null)
                    {
                        BindValue(modelProperty, val, bindingContext);
                    }
                }
            }

            if (modelType.IsArray())
            {
                var generictoArrayMethod = ToArrayMethodInfo.MakeGenericMethod(new[] { genericType });
                return generictoArrayMethod.Invoke(null, new[] { bindingContext.Model });
            }
            return bindingContext.Model;
        }