private void applyToProperty(object model, PropertyInfo property, IBindManager binder, string prefix, string remainder)
 {
     // If (after taking the prefix into account) this is a complex property change
     // Recurse, using the object referred to by the first part of the property name
     // as the new model to apply the change to.
     if (split(remainder).Count() > 1)
     {
         var value = getValue(model, property);
         applyTo(value, binder, property.PropertyType, ExpressionHelper.Join(prefix, property.Name));
     }
     // Otherwise, if we are now at a simple property change, just bind the value
     // and set the appropriate property
     else
     {
         var existingValue = property.GetValue(model, null);
         var value         = binder.Bind(wrapped.Value, property.PropertyType, existingValue);
         if (isEntityCollection(property) && existingValue != null)
         {
             // do nothing, its contents were already updated by the binder,
             // and it's an error to use the property setter for an entity collection
         }
         else
         {
             property.SetValue(model, value, null);
         }
     }
 }
예제 #2
0
        public object Bind(string raw, Type type, object existingValue)
        {
            if (raw == null)
            {
                return(null);
            }

            return(bindManager.Bind(raw, underlyingType(type), existingValue));
        }
예제 #3
0
 protected virtual void fillCollection <ItemType>(ICollection <ItemType> collection, string raw)
 {
     foreach (var reference in raw.Split(new char[] { ',' }).Where(r => !string.IsNullOrEmpty(r)))
     {
         var item = bindManager.Bind <ItemType>(reference);
         if (collection.All(i => !equalCollectionItems(i, item)))
         {
             collection.Add(item);
         }
     }
 }
예제 #4
0
        /// <summary>
        /// Retrieve the values that a single property has gone through, most recent
        /// first (descending date order).
        /// </summary>
        public virtual IEnumerable<IChange<TValue, TPrincipal>> ChangesTo<TModel, TValue>(TModel model, Expression<Func<TModel, TValue>> property)
        {
            string typeName = typeof(TModel).Name;
            string propertyName = property.GetPropertyName();
            string propertyPrefix = propertyName + ".";
            string reference = historyContext.GetReferenceForObject(model);
            var propertyFunc = property.Compile();
            
            var objectChanges = changesTo(model)
                .SelectMany(o => o.PropertyChanges)
                .Where(p => p.PropertyName == propertyName || p.PropertyName.StartsWith(propertyPrefix))
                .AsEnumerable()
                .GroupBy(p => p.ObjectChange)
                .Select(g => new FilteredObjectChange<TPrincipal>(g.Key, g));

            // If the propert expression refers to a complex type then we will not have any changes
            // directly to that property. Instead we will see changes to sub-properties.
            // We retrieve the history differently for complex types, so here we distinguish which
            // case we are in by looking at the first change.
            var sample = objectChanges.SelectMany(o => o.PropertyChanges).FirstOrDefault();
            if (sample != null && sample.PropertyName.StartsWith(propertyPrefix))
            {
                // Construct a "seed" instance of the complex type, and then apply changes to it in order
                // to reconstruct the intermediate states.
                return applyChangesTo(HistoryHelpers.Instantiate<TValue>(), objectChanges, propertyName)
                    .OrderByDescending(c => c.Timestamp);
            }
            else
            {
                // Just directly bind the simple property values
                return objectChanges
                    .OrderByDescending(o => o.ChangeSet.Timestamp)
                    .SelectMany(o => o.PropertyChanges)
                    .Select(p => Change.FromObjectChange(binder.Bind<TValue>(p.Value), p.ObjectChange));
            }
        }