/// <summary>
        /// 卸载指定插件树节点对应的自定义对象。
        /// </summary>
        /// <param name="node">指定要卸载对象的挂靠节点。</param>
        /// <returns>如果成功卸载则返回被卸载的对象,否则返回空(null)。</returns>
        /// <exception cref="System.ArgumentNullException">当<paramref name="node"/>参数为空(null)。</exception>
        /// <exception cref="System.ArgumentException">当<paramref name="node"/>参数的<see cref="Zongsoft.Plugins.PluginTreeNode.Tree"/>属性与当前插件树对象不是同一个引用。</exception>
        /// <remarks>
        ///		<para>注意:当前该方法的实现是不完备的,请谨慎使用!</para>
        ///		<para>将<paramref name="node"/>参数指定的节点对象的Value属性置空,导致该节点类型成为路径节点(即空节点)。</para>
        ///		<para>如果<paramref name="node"/>参数指定的节点对象没有子节点了,则将该节点从插件树中删除,否则保留。</para>
        /// </remarks>
        public object Unmount(PluginTreeNode node)
        {
            if (node == null)
            {
                return(null);
            }

            if (!object.ReferenceEquals(node.Tree, this))
            {
                throw new ArgumentException();
            }

            //以永不构建的方式获取当前节点的目标对象
            var value = node.UnwrapValue(ObtainMode.Never, null);

            //将当前节点置空
            node.Value = null;

            //判断当前节点是否为叶子节点,如果是则将其删除
            if (node.Children.Count == 0)
            {
                node.Remove();
            }

            //返回被卸载的目标对象
            return(value);
        }
Exemple #2
0
        internal static Type GetOwnerElementType(PluginTreeNode node)
        {
            var ownerNode = node.Tree.GetOwnerNode(node);

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

            var ownerType = ownerNode.ValueType;

            if (ownerType == null)
            {
                var owner = ownerNode.UnwrapValue(ObtainMode.Never);

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

                ownerType = owner.GetType();
            }

            var elementType = GetImplementedCollectionElementType(ownerType);

            if (elementType != null)
            {
                return(elementType);
            }

            MemberInfo[] members         = null;
            var          memberAttribute = ownerType.GetCustomAttribute <DefaultMemberAttribute>(true);

            if (memberAttribute != null)
            {
                members = ownerType.GetMember(memberAttribute.MemberName, BindingFlags.Public | BindingFlags.Instance);
            }
            else
            {
                var propertyAttribute = ownerType.GetCustomAttribute <DefaultPropertyAttribute>(true);
                if (propertyAttribute != null)
                {
                    members = ownerType.GetMember(propertyAttribute.Name, BindingFlags.Public | BindingFlags.Instance);
                }
            }

            if (members != null && members.Length == 1)
            {
                switch (members[0].MemberType)
                {
                case MemberTypes.Field:
                    return(GetImplementedCollectionElementType(((FieldInfo)members[0]).FieldType));

                case MemberTypes.Property:
                    return(GetImplementedCollectionElementType(((PropertyInfo)members[0]).PropertyType));
                }
            }

            return(null);
        }
Exemple #3
0
 internal AppenderContext(object value, PluginTreeNode node, object container, PluginTreeNode containerNode, AppenderBehavior behaviour)
 {
     _syncRoot      = new object();
     _node          = node ?? throw new ArgumentNullException(nameof(node));
     _value         = value;
     _container     = container;
     _containerNode = containerNode;
     _behaviour     = behaviour;
 }
Exemple #4
0
        internal PluginExtendedProperty(PluginElement owner, string name, PluginTreeNode valueNode, Plugin plugin) : base(owner, name, valueNode)
        {
            if (plugin == null)
            {
                throw new ArgumentNullException(nameof(plugin));
            }

            _plugin = plugin;
        }
        /// <summary>
        /// 获取指定节点的所有者对象。
        /// </summary>
        /// <param name="node">要获取的所有者对象的节点。</param>
        /// <returns>返回指定节点的所有者对象,如果没有则返回空(null)。</returns>
        /// <remarks>
        ///		<para>注意:该方法不会引起上级节点的创建动作,可确保在<see cref="Zongsoft.Plugins.IBuilder"/>构建器中使用而不会导致循环创建的问题。</para>
        /// </remarks>
        internal object GetOwner(PluginTreeNode node)
        {
            var ownerNode = this.GetOwnerNode(node);

            if (ownerNode != null)
            {
                return(ownerNode.Value);
            }

            return(null);
        }
        internal protected PluginElementProperty(PluginElement owner, string name, PluginTreeNode valueNode)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentNullException(nameof(name));
            }

            _name      = name.Trim();
            _owner     = owner ?? throw new ArgumentNullException(nameof(owner));
            _valueNode = valueNode ?? throw new ArgumentNullException(nameof(valueNode));
            _rawValue  = valueNode.FullPath;
        }
        /// <summary>
        /// 挂载对象到插件树中。
        /// </summary>
        /// <param name="path">要挂载的路径。</param>
        /// <param name="value">要挂载的对象。</param>
        /// <param name="position">当挂载路径对应的叶子节点不存在时,由该参数确认其插入的位置,如果该参数为空(null)或空字符串则默认追加到同级节点的最后。</param>
        /// <returns>挂载成功则返回真(True)否则返回假(False)。</returns>
        /// <remarks>
        ///		<para>注意:如果<paramref name="path"/>参数指定的路径对应的插件树节点已经存在,并且节点类型为<seealso cref="Zongsoft.Plugins.PluginTreeNodeType.Builtin"/>并且已经构建完成则返回假(False)。</para>
        ///		<para>如果符合上面的条件,则激发<seealso cref="Zongsoft.Plugins.PluginTree.Mounting"/>事件,挂入成功后激发<seealso cref="Zongsoft.Plugins.PluginTree.Mounted"/>事件。</para>
        ///		<para>如果<paramref name="path"/>参数指定的路径不存在,则创建它并挂载由<paramref name="value"/>参数指定的对象。</para>
        ///	</remarks>
        public bool Mount(string path, object value, string position)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentNullException("path");
            }

            //确认要挂载的路径对应的节点
            PluginTreeNode node = this.EnsurePath(path, position);

            return(this.Mount(node, value));
        }
        private void UnmountItem(Plugin plugin, string path)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentNullException("path");
            }

            PluginTreeNode node = this.Find(path);

            if (node != null)
            {
                this.UnmountItem(plugin, node);
            }
        }
        /// <summary>
        /// 生成指定插件节点对应的目标对象。
        /// </summary>
        /// <param name="node">指定要构建的插件树节点。</param>
        /// <param name="parameter">调用者需要传递给构建器的参数对象。</param>
        /// <param name="build">由调用者指定的构建委托,如果为空则使用对应的构建器的构建动作。</param>
        /// <returns>返回构建成功的目标,如果指定的<paramref name="node"/>类型不是<see cref="PluginTreeNodeType.Builtin"/>则返回节点的<see cref="PluginTreeNode.Value"/>属性值。</returns>
        public object Build(PluginTreeNode node, object parameter, Action <Builders.BuilderContext> build)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (_status != PluginTreeStatus.Loaded)
            {
                throw new InvalidOperationException();
            }

            return(node.Build(parameter, build));
        }
Exemple #10
0
        internal PluginTree(PluginContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            _syncRoot = new object();

            _loader   = null;
            _context  = context;
            _status   = PluginTreeStatus.None;
            _resolver = new PluginResolver(this);
            _rootNode = new PluginTreeNode(this);
        }
Exemple #11
0
        public object Build(string path, object parameter, Action <Builders.BuilderContext> build)
        {
            if (_status == PluginTreeStatus.None)
            {
                throw new InvalidOperationException();
            }

            PluginTreeNode node = this.Find(path);

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

            return(this.Build(node, parameter, build));
        }
Exemple #12
0
        /// <summary>
        /// 卸载指定路径的自定义对象。
        /// </summary>
        /// <param name="path">指定要卸载的路径。</param>
        /// <returns>如果成功卸载则返回被卸载的对象,否则返回空(null)。</returns>
        /// <exception cref="System.ArgumentNullException">当<paramref name="path"/>参数为空或全空字符串。</exception>
        /// <exception cref="System.ArgumentException">当<paramref name="path"/>参数对应的节点对象的<see cref="Zongsoft.Plugins.PluginTreeNode.Tree"/>属性与当前插件树对象不是同一个引用。</exception>
        /// <remarks>
        ///		<para>如果<paramref name="path"/>参数指定的路径不存在,则返回失败。</para>
        ///		<para>如果<paramref name="path"/>参数对应的<seealso cref="Zongsoft.Plugins.PluginTreeNode"/>对象的节点类型(即<seealso cref="Zongsoft.Plugins.PluginTreeNode.NodeType"/>属性)不是自定义对象,则返回失败。</para>
        ///		<para>有关本方法的卸载逻辑请参考<see cref="Unmount(PluginTreeNode)"/>重载方法。</para>
        /// </remarks>
        public object Unmount(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentNullException("path");
            }

            PluginTreeNode node = this.Find(path);

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

            return(this.Unmount(node));
        }
Exemple #13
0
        protected virtual void OnStop()
        {
            if (string.IsNullOrEmpty(_startupPath))
            {
                return;
            }

            //获取启动路径对应的节点对象
            PluginTreeNode startupNode = _applicationContext.PluginContext.PluginTree.Find(_startupPath);

            //停止启动路径下的所有工作者
            if (startupNode != null)
            {
                this.StopWorkers(startupNode);
            }
        }
Exemple #14
0
        /// <summary>
        /// 获取或创建指定路径的插件树节点。
        /// </summary>
        /// <param name="path">要获取或创建的插件路径。</param>
        /// <param name="position">当创建指定路径对应的叶子节点时,由该参数确认其插入的位置,如果该参数为空(null)或空字符串则默认追加到同级节点的最后。</param>
        /// <param name="existed">输出参数,如果指定的路径已存在则返回真(true),否则返回假(false)。</param>
        /// <returns>返回存在的或者新建的节点对象,如果指定的<paramref name="path"/>路径参数是已存在的,则返回其对应的节点对象否则新建该节点。</returns>
        public PluginTreeNode EnsurePath(string path, string position, out bool existed)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentNullException("path");
            }

            existed = true;
            PluginTreeNode node = _rootNode;

            string[] parts = path.Split('/');

            lock (_syncRoot)
            {
                for (int i = 0; i < parts.Length; i++)
                {
                    string part = parts[i];

                    if (string.IsNullOrEmpty(part))
                    {
                        if (node == _rootNode)
                        {
                            continue;
                        }
                        else
                        {
                            throw new PluginException("Invlaid '" + path + "' path.");
                        }
                    }

                    PluginTreeNode child = node.Children[part];

                    if (child == null)
                    {
                        child = new PluginTreeNode(this, part);
                        node.Children.Insert(child, position);
                        existed = false;
                    }

                    node = child;
                }
            }

            return(node);
        }
        internal static Type GetOwnerElementType(PluginTreeNode node)
        {
            var ownerNode = node.Tree.GetOwnerNode(node);

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

            var ownerType = ownerNode.ValueType;

            if (ownerType == null)
            {
                var owner = ownerNode.UnwrapValue(ObtainMode.Never);

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

                ownerType = owner.GetType();
            }

            var elementType = GetImplementedCollectionElementType(ownerType);

            if (elementType != null)
            {
                return(elementType);
            }

            var attribute = ownerType.GetCustomAttribute <System.ComponentModel.DefaultPropertyAttribute>(true);

            if (attribute != null)
            {
                var property = ownerType.GetProperty(attribute.Name, BindingFlags.Public | BindingFlags.Instance);

                if (property != null)
                {
                    return(GetImplementedCollectionElementType(property.PropertyType));
                }
            }

            return(null);
        }
Exemple #16
0
        private void StartWorkers(PluginTreeNode node, string[] args)
        {
            if (node == null)
            {
                return;
            }

            object target = node.UnwrapValue(ObtainMode.Auto);

            if (target is IWorker worker && worker.Enabled)
            {
                worker.Start(args);
            }

            foreach (PluginTreeNode child in node.Children)
            {
                this.StartWorkers(child, args);
            }
        }
Exemple #17
0
        private void UnmountItem(Plugin plugin, PluginTreeNode node)
        {
            if (node == null)
            {
                return;
            }

            if (plugin != null)
            {
                foreach (PluginTreeNode child in node.Children)
                {
                    this.UnmountItem(plugin, child);
                }
            }

            if (node.NodeType == PluginTreeNodeType.Custom)
            {
                this.Unmount(node);
                return;
            }

            if (node.NodeType == PluginTreeNodeType.Builtin)
            {
                Builtin builtin = (Builtin)node.Value;

                if (string.ReferenceEquals(builtin.Plugin, plugin))
                {
                    IBuilder builder = node.Plugin.GetBuilder(builtin.BuilderName);
                    if (builder != null)
                    {
                        builder.Destroy(Builders.BuilderContext.CreateContext(builder, builtin, this));
                    }

                    plugin.UnregisterBuiltin(builtin);
                    node.Value = null;
                }
            }

            if (node.Children.Count < 1 && node.Parent != null)
            {
                node.Parent.Children.Remove(node);
            }
        }
Exemple #18
0
        private void StopWorkers(PluginTreeNode node)
        {
            if (node == null)
            {
                return;
            }

            foreach (PluginTreeNode child in node.Children)
            {
                this.StopWorkers(child);
            }

            object target = node.UnwrapValue(ObtainMode.Never);

            if (target is IWorker worker)
            {
                worker.Stop();
            }
        }
Exemple #19
0
        internal AppenderContext(PluginContext pluginContext, object value, PluginTreeNode node, object container, PluginTreeNode containerNode, AppenderBehavior behaviour)
        {
            if (pluginContext == null)
            {
                throw new ArgumentNullException("pluginContext");
            }

            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            _syncRoot      = new object();
            _pluginContext = pluginContext;
            _node          = node;
            _value         = value;
            _container     = container;
            _containerNode = containerNode;
            _behaviour     = behaviour;
        }
Exemple #20
0
        public PluginTreeNode GetOwnerNode(PluginTreeNode node)
        {
            if (node == null)
            {
                return(null);
            }

            var parent = node.Parent;

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

            if (parent.NodeType == PluginTreeNodeType.Empty)
            {
                return(this.GetOwnerNode(parent));
            }

            return(parent);
        }
Exemple #21
0
        internal object ResolvePath(string pathText, PluginTreeNode origin, ObtainMode obtainMode)
        {
            if (string.IsNullOrWhiteSpace(pathText))
            {
                throw new ArgumentNullException(nameof(pathText));
            }

            var expression = PluginPath.Parse(pathText);
            var node       = origin.Find(expression.Path);

            if (node == null)
            {
                throw new PluginException($"Not found the PluginTreeNode with '{expression.Path}' path.");
            }

            try
            {
                //获取指定路径的目标对象
                object target = node.UnwrapValue(obtainMode, this, null);

                if (target != null && expression.Members.Length > 0)
                {
                    return(Reflection.MemberAccess.GetMemberValue <object>(target, expression.Members));
                }

                return(target);
            }
            catch (Exception ex)
            {
                var fileName = string.Empty;

                if (origin != null && origin.Plugin != null)
                {
                    fileName = System.IO.Path.GetFileName(origin.Plugin.FilePath);
                }

                throw new PluginException(string.Format("Resolve target error from '{0}' path in '{1}' plugin file.", pathText, fileName), ex);
            }
        }
Exemple #22
0
        private void EnsureNodes(PluginTreeNode node)
        {
            if (node == null)
            {
                return;
            }

            if (node.NodeType == PluginTreeNodeType.Builtin)
            {
                if (!((Builtin)node.Value).IsBuilded)
                {
                    node.Build();
                }

                return;
            }

            foreach (var child in node.Children)
            {
                this.EnsureNodes(child);
            }
        }
Exemple #23
0
        public bool Mount(PluginTreeNode node, object value)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            if (value is Builtin || value is PluginElement || value is PluginTree || value is PluginContext)
            {
                return(false);
            }

            //激发“Mounting”事件
            this.OnMounting(new PluginMountEventArgs(node.FullPath, value));

            //更新节点值
            node.Value = value;

            //激发“Mounted”事件
            this.OnMounted(new PluginMountEventArgs(node.FullPath, value));

            return(true);
        }
			internal Sitemap(Zongsoft.Plugins.PluginTreeNode sitemapNode)
			{
				if(sitemapNode == null)
					throw new ArgumentNullException("sitemapNode");

				_sitemapNode = sitemapNode;
			}
Exemple #25
0
        internal object ResolvePath(string pathText, PluginTreeNode origin)
        {
            ObtainMode mode;

            return(this.ResolvePath(PluginPath.PreparePathText(pathText, out mode), origin, mode));
        }
Exemple #26
0
 public object Build(PluginTreeNode node)
 {
     return(this.Build(node, null, null));
 }
Exemple #27
0
 public object Build(PluginTreeNode node, object parameter)
 {
     return(this.Build(node, parameter, null));
 }