protected override void OnInitialize()
        {
            var g = this.AddActivableSection( R.WordPredictionSectionName.ToLower(), R.WordPredictionConfig, this, h => h.ActivateWordPrediction, this );

            var c = new ConfigItemProperty<int>( ConfigManager, this, CK.Reflection.ReflectionHelper.GetPropertyInfo( this, e => e.MaxSuggestedWords ) );
            c.DisplayName = R.WordPredictionMaxSuggestedWords;
            g.Items.Add( c );

            var p = new ConfigItemProperty<bool>( ConfigManager, this, CK.Reflection.ReflectionHelper.GetPropertyInfo( this, e => e.InsertSpaceAfterPredictedWord ) );
            p.DisplayName = R.WordPredictionInsertSpace;
            g.Items.Add( p );

            var engine = new ConfigItemProperty<bool>( ConfigManager, this, CK.Reflection.ReflectionHelper.GetPropertyInfo( this, e => e.UsesSemanticPrediction ) );
            engine.DisplayName = R.WordPredictionUseSemanticPrediction;
            g.Items.Add( engine );

            var filter = new ConfigItemProperty<bool>( ConfigManager, this, CK.Reflection.ReflectionHelper.GetPropertyInfo( this, e => e.FilterAlreadyShownWords ) );
            filter.DisplayName = R.WordPredictionFilterAlreadySuggestedWord;
            g.Items.Add( filter );

            var contextEditor = new ConfigItemProperty<bool>( ConfigManager, this, CK.Reflection.ReflectionHelper.GetPropertyInfo( this, e => e.DisplayContextEditor ) );
            contextEditor.DisplayName = R.WordPredictionDisplayPredictionEditorWindow;
            g.Items.Add( contextEditor );

            base.OnInitialize();
        }
 set => SetValue(ConfigItemProperty, value);
        private static ConfigItemNode GetNode(object configItem, DescriptorInfo descriptor)
        {
            ConfigItemNode result = new ConfigItemNode
            {
                Properties = new ObservableCollection <ConfigItemProperty>(),
                SubNodes   = new ObservableCollection <ConfigItemNode>()
            };

            var propertyInfos = configItem.GetType().GetProperties(BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Instance);

            foreach (var pInfo in propertyInfos)
            {
                var setter = pInfo.GetSetMethod();
                if (setter == null)
                {
                    continue;
                }
                var value           = pInfo.GetValue(configItem);
                var valueDescriptor = GetOrCreateDescriptorInfo(pInfo.Name, pInfo.PropertyType, descriptor.PropertyDescriptors,
                                                                pInfo.GetCustomAttribute(typeof(DescriptorAttribute)) as DescriptorAttribute);
                if (IsValue(pInfo.PropertyType, out bool isList))
                {
                    //property
                    if (value == null && isList)
                    {
                        //构造默认list
                        value = valueDescriptor.DefaultValue ?? new ObservableCollection <object>();
                    }

                    if (isList)
                    {
                        value = ConvertToListValue(value, valueDescriptor);
                    }

                    ConfigItemProperty tmpP = null;
                    if (isList)
                    {
                        tmpP = new ListItemProperty();
                    }
                    else
                    {
                        tmpP = new ConfigItemProperty();
                    }

                    tmpP.Descriptor = valueDescriptor;
                    tmpP.Value      = value;

                    if (value == null && valueDescriptor.DefaultValue != null)
                    {
                        //没有值,就使用默认值
                        tmpP.Value = valueDescriptor.DefaultValue;
                    }
                    result.Properties.Add(tmpP);
                }
                else
                {
                    //node
                    if (value == null)
                    {
                        value = Activator.CreateInstance(pInfo.PropertyType);
                    }
                    var subPropertyTypes = value.GetType().GetProperties(BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Instance);
                    var tmpNode          = GetNode(value, valueDescriptor);
                    result.SubNodes.Add(tmpNode);
                }
            }
            //拷贝,不破坏元对象。只需要保留当前级的信息,节约内存
            string oldPropertyName = descriptor.PropertyName;

            descriptor = DeepClone(descriptor);
            //因为propertyName没有 setter,所以需要重新复制
            DescriptorInfo.SetPropertyName(oldPropertyName, descriptor);
            result.Descriptor = descriptor;
            return(result);
        }