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); }
public PropertyChangeSubscriber(object effectiveObject, PropertyPathItem <T> pathItem, Action <PathItemBase <T> > onChanged) : base(effectiveObject, pathItem, onChanged) { var notifyPropertyChange = effectiveObject as INotifyPropertyChanged; if (notifyPropertyChange != null) { Subscribe(notifyPropertyChange); } var ancestor = InitAncestor(); if (ancestor != null) { Ancestors.Add(ancestor); } }