private PropertyTreeMetaObject DoOperatorBind(PropertyTreeBinderImpl parent, PropertyTreeMetaObject target, PropertyTreeNavigator navigator, OperatorDefinition op)
            {
                OperatorDefinition addon = op;

                if (addon.DefaultParameter != null) {
                    Type itemType = ((PropertyTreeFactoryDefinition) addon).OutputType;
                    // TODO Use service activation (we have the output type)

                    var item = target.CreateChild(itemType);
                    var model = parent.Bind(item, navigator, null);
                    var args = new Dictionary<string, PropertyTreeMetaObject>
                    {
                        { addon.DefaultParameter.Name, model }
                    };

                    try {
                        target.BindAddChild(op, args);

                    } catch (Exception ex) {
                        if (ex.IsCriticalException())
                            throw;

                        parent.errors.BadAddChild(target.ComponentType, ex, navigator.FileLocation);
                    }

                } else {
                    // TODO The number and kinds of arguments are constrained.  This should probably
                    // be enforced within schema operator reflection (spec)

                    Action<IReadOnlyDictionary<string, PropertyTreeMetaObject>> func;
                    var children = NodeList.Create(SelectChildren(navigator));

                    switch (addon.OperatorType) {
                        case OperatorType.Add:
                            func = args => {
                                var child = target.BindAddChild(addon, args);

                                if (child.ShouldBindChildren) {
                                    parent.BindChildNodes(child, navigator, children);
                                }
                            };
                            break;

                        case OperatorType.Remove:
                            func = args => target.BindRemoveChild(addon, args);
                            break;

                        case OperatorType.Clear:
                        default:
                            func = args => target.BindClearChildren(addon, args);
                            break;
                    }

                    var services = parent.GetBasicServices(navigator);
                    var args2 = parent.ExtractParameterDictionary(op, target, services, children);
                    func(args2);
                }

                return target;
            }
            public override PropertyTreeMetaObject Process(
                PropertyTreeBinderImpl parent,
                PropertyTreeMetaObject target,
                PropertyTreeNavigator self,
                NodeList children)
            {
                if (!(target is UntypedToTypedMetaObject))
                {
                    return(target);
                }

                if (!children.Any())
                {
                    return(target);
                }

                try {
                    // TODO Only supports one child (lame spec)
                    var rootType = target.Root.ComponentType;
                    var types    = children.Select(t => ConvertToType(t, rootType)).ToArray();

                    target = target.BindGenericParameters(types);
                } catch (PropertyTreeException) {
                    throw;
                } catch (Exception ex) {
                    if (ex.IsCriticalException())
                    {
                        throw;
                    }

                    parent._errors.CouldNotBindGenericParameters(target.ComponentType, ex, self.FileLocation);
                }

                parent.Bind(target, children.First(), null);
                children.Clear();
                return(target);
            }
            private PropertyTreeMetaObject DoOperatorBind(PropertyTreeBinderImpl parent, PropertyTreeMetaObject target, PropertyTreeNavigator navigator, OperatorDefinition op)
            {
                OperatorDefinition addon = op;

                if (addon.DefaultParameter != null)
                {
                    Type itemType = addon.OutputType;
                    // TODO Use service activation (we have the output type)

                    var item  = target.CreateChild(itemType);
                    var model = parent.Bind(item, navigator, null);
                    var args  = new Dictionary <string, PropertyTreeMetaObject>
                    {
                        { addon.DefaultParameter.Name, model }
                    };

                    try {
                        target.BindAddChild(op, args);
                    } catch (PropertyTreeException) {
                        throw;
                    } catch (Exception ex) {
                        if (ex.IsCriticalException())
                        {
                            throw;
                        }

                        parent._errors.BadAddChild(target.ComponentType, ex, navigator.FileLocation);
                    }
                }
                else
                {
                    // TODO The number and kinds of arguments are constrained.  This should probably
                    // be enforced within schema operator reflection (spec)

                    Action <IReadOnlyDictionary <string, PropertyTreeMetaObject> > func;
                    var children = NodeList.Create(SelectChildren(navigator));

                    switch (addon.OperatorType)
                    {
                    case OperatorType.Add:
                        func = args => {
                            var child = target.BindAddChild(addon, args);

                            if (child.ShouldBindChildren)
                            {
                                parent.BindChildNodes(child, navigator, children);
                            }
                        };
                        break;

                    case OperatorType.Remove:
                        func = args => target.BindRemoveChild(addon, args);
                        break;

                    case OperatorType.Clear:
                    default:
                        func = args => target.BindClearChildren(addon, args);
                        break;
                    }

                    var services = parent.GetBasicServices(navigator);
                    var args2    = parent.ExtractParameterDictionary(op, target, services, children);
                    func(args2);
                }

                return(target);
            }
            private void DoPropertyBind(PropertyTreeBinderImpl parent,
                                        PropertyTreeMetaObject target,
                                        PropertyTreeNavigator navigator,
                                        PropertyDefinition property)
            {
                object ancestor = null;
                PropertyTreeMetaObject ancestorMeta = null;

                if (property.IsExtender) {
                    var ancestorType = property.DeclaringTreeDefinition.SourceClrType;
                    ancestorMeta = target.GetAncestors().Cast<PropertyTreeMetaObject>().FirstOrDefault(
                        t => ancestorType.IsAssignableFrom(t.ComponentType));

                    if (ancestorMeta != null)
                        ancestor = ancestorMeta.Component;
                }

                var component = target.Component;
                PropertyTreeMetaObject propertyTarget = target.CreateChild(property, navigator.QualifiedName, ancestorMeta);

                var services = new PropertyBindContext(
                    component,
                    property,
                    ServiceProvider.Compose(ServiceProvider.FromValue(navigator), parent))
                {
                    LineNumber = navigator.LineNumber,
                    LinePosition = navigator.LinePosition,
                };

                propertyTarget = parent.Bind(propertyTarget, navigator, services);
                target.BindSetMember(property, navigator.QualifiedName, propertyTarget, ancestorMeta, services);
            }