public PropertyPathItem(Func <object, object> propertyOrFieldGetter, string propertyOrFieldName, PathItemBase <T> ancestor, Action <T> updateDependentPropertyOrFieldAction) : base(ancestor, updateDependentPropertyOrFieldAction) { _propertyOrFieldGetter = propertyOrFieldGetter; _propertyOrFieldName = propertyOrFieldName; }
private static PathItemBase <T> BuildPath(Expression <Func <T, object> > pathExpession, Action <T> calculateAndSet) { var convertExpression = pathExpession.Body as UnaryExpression; if (convertExpression != null && (convertExpression.NodeType != ExpressionType.Convert || convertExpression.Type != typeof(object))) { throw new NotSupportedException(string.Format( "Unary expression {0} is not supported. Only \"convert to object\" expression is allowed in the end of path.", convertExpression)); } var currentExpression = convertExpression != null ? convertExpression.Operand : pathExpession.Body; PathItemBase <T> rootPathItem = null; while (!(currentExpression is ParameterExpression)) { var methodCall = currentExpression as MethodCallExpression; if (methodCall != null) { if (!methodCall.Method.IsGenericMethod || !methodCall.Method.GetGenericMethodDefinition().Equals(CollectionExtensions.EachElementMethodInfo)) { throw new NotSupportedException(string.Format("Call of method {0} is not supported. Only {1} call is supported for collections in path", methodCall.Method, CollectionExtensions.EachElementMethodInfo)); } rootPathItem = new CollectionPathItem <T>(rootPathItem, rootPathItem == null ? calculateAndSet : null); var methodCallArgument = methodCall.Arguments.Single(); currentExpression = methodCallArgument; continue; } var memberExpression = currentExpression as MemberExpression; if (memberExpression == null) { throw new NotSupportedException(string.Format("Expected expression is member expression. Expression {0} is not supported.", currentExpression)); } var property = memberExpression.Member; var compiledGetter = BuildGetter(memberExpression.Expression.Type, property.Name); rootPathItem = new PropertyPathItem <T>(compiledGetter, property.Name, rootPathItem, rootPathItem == null ? calculateAndSet : null); currentExpression = memberExpression.Expression; } //The chain doesn't contain any element (i.e. the expression contains only root object root => root) if (rootPathItem == null) { throw new NotSupportedException(string.Format("The path {0} is too short. It contains a root object only.", pathExpession)); } rootPathItem = new PropertyPathItem <T>(o => o, string.Empty, rootPathItem, null); return(rootPathItem); }
private void ProvokeDependentPropertiesUpdate(PathItemBase <T> pathItem) { while (pathItem != null) { if (pathItem.UpdateDependentPropertyOrFieldAction != null) { pathItem.UpdateDependentPropertyOrFieldAction(_trackedObject); } pathItem = pathItem.Ancestor; } }
protected SubscriberBase(object effectiveObject, PathItemBase <T> pathItem, Action <PathItemBase <T> > onChanged) { if (effectiveObject == null) { throw new ArgumentNullException("effectiveObject"); } if (pathItem == null) { throw new ArgumentNullException("pathItem"); } if (onChanged == null) { throw new ArgumentNullException("onChanged"); } _effectiveObject = effectiveObject; PathItem = pathItem; OnChanged = onChanged; }
public static SubscriberBase CreateSubscriber(object effectiveObject, PathItemBase <T> pathItem, Action <PathItemBase <T> > onChanged) { var propertyPathItem = pathItem as PropertyPathItem <T>; if (propertyPathItem != null) { if (propertyPathItem.PropertyOrFieldName == string.Empty) { return(new RootObjectSubscriber(effectiveObject, pathItem, onChanged)); } return(new PropertyChangeSubscriber(effectiveObject, propertyPathItem, onChanged)); } var collectionPathItem = pathItem as CollectionPathItem <T>; if (collectionPathItem != null) { return(new CollectionChangeSubscriber(effectiveObject, collectionPathItem, onChanged)); } throw new ArgumentException(string.Format("Unknown path item type: {0}", pathItem.GetType()), "pathItem"); }
public RootObjectSubscriber(object effectiveObject, PathItemBase <T> pathItem, Action <PathItemBase <T> > onChanged) : base(effectiveObject, pathItem, onChanged) { Ancestors.Add(CreateSubscriber(effectiveObject, pathItem.Ancestor, onChanged)); }
private void OnPropertyChanged(PathItemBase <T> subscriber) { ProvokeDependentPropertiesUpdate(subscriber); }
protected PathItemBase(PathItemBase <T> ancestor, Action <T> updateDependentPropertyOrFieldAction) { _ancestor = ancestor; _updateDependentPropertyOrFieldAction = updateDependentPropertyOrFieldAction; }
public CollectionPathItem(PathItemBase <T> ancestor, Action <T> updateDependentPropertyOrFieldAction) : base(ancestor, updateDependentPropertyOrFieldAction) { }