public override void OnInspectorGUI()
    {
        EditorGUIUtility.labelWidth = 80;

        GUI.changed = false;

        FieldInfo         field      = typeof(LuaInjectionData).GetField("m_InjectionList", BindingFlags.Instance | BindingFlags.NonPublic);
        List <Injection4> injections = field.GetValue(m_LuaInjectionData) as List <Injection4>;

        DrawArray(injections, true);

        GUILayout.BeginHorizontal();
        Undo.RecordObject(m_LuaInjectionData, "Injection.Count");
        if (GUILayout.Button("+"))
        {
            Injection4 injection = new Injection4();
            int        count     = injections.Count;
            if (count > 0)
            {
                injection.Type = injections[count - 1].Type;
            }
            injections.Add(injection);
        }
        GUILayout.EndHorizontal();

        field.SetValue(m_LuaInjectionData, injections);

        if (GUI.changed)
        {
            EditorUtility.SetDirty(m_LuaInjectionData);
        }
    }
    private List <T> DrawArray <T>(List <T> array, bool isDict) where T : Injection, new()
    {
        Color oldColor = GUI.backgroundColor;

        for (int index = 0, realIndex = 0; index < array.Count; index++)
        {
            string styleName = null;

            T injection = array[index] ?? new T();
            if (injection.Type == InjectionType.List || injection.Type == InjectionType.Dict)
            {
                if (injection is IFoldable)
                {
                    IFoldable foldable = injection as IFoldable;
                    if (foldable.IsFolded)
                    {
                        styleName           = "As TextArea";
                        GUI.backgroundColor = Color.white * 0.8F;
                        GUILayout.Space(-2F);
                    }
                }
            }

            if (string.IsNullOrEmpty(styleName))
            {
                GUILayout.BeginHorizontal();
            }
            else
            {
                GUILayout.BeginHorizontal(styleName);
            }

            Undo.RecordObject(m_LuaInjectionData, "Injection.Count");
            bool remove = GUILayout.Button("×", GUILayout.Width(20F), GUILayout.Height(14F));

            GUILayout.Label("Type:", GUILayout.Width(40F));
            Undo.RecordObject(m_LuaInjectionData, "Injection.Type");
            injection.Type = (InjectionType)EditorGUILayout.EnumPopup(injection.Type, GUILayout.Width(75F));
            if (injection.Type == InjectionType.List || injection.Type == InjectionType.Dict)
            {
                if (typeof(T) == typeof(Injection))
                {
                    injection.Type = InjectionType.String;
                }
            }
            GUI.enabled = index > 0;
            Undo.RecordObject(m_LuaInjectionData, "Injection.Up");
            bool up = GUILayout.Button("▲", GUILayout.Width(20F), GUILayout.Height(14F));
            GUI.enabled = index < array.Count - 1;
            Undo.RecordObject(m_LuaInjectionData, "Injection.Down");
            bool down = GUILayout.Button("▼", GUILayout.Width(20F), GUILayout.Height(14F));
            GUI.enabled = true;

            if (injection.Type == InjectionType.Space)
            {
                injection.Name  = null;
                injection.Value = null;
            }
            else
            {
                if (isDict)
                {
                    GUILayout.Label("Name:", GUILayout.Width(40F));
                    injection.Name = EditorGUILayout.TextField(injection.Name ?? "", GUILayout.MaxWidth(120F));
                }
                else
                {
                    GUILayout.Label("Index:", GUILayout.Width(40F));
                    GUI.enabled = false;
                    EditorGUILayout.IntField(realIndex + 1, GUILayout.Width(30F));
                    GUI.enabled = true;
                }

                object value = injection.Value;
                object newValue;
                if (injection.Type == InjectionType.List || injection.Type == InjectionType.Dict)
                {
                    newValue = value;
                    bool valueIsDict = injection.Type == InjectionType.Dict;
                    if (typeof(T) == typeof(Injection4))
                    {
                        Injection4 inj = injection as Injection4;
                        if (!(newValue is List <Injection3>))
                        {
                            newValue = new List <Injection3>();
                        }
                        inj.IsFolded = DrawArrayValue(newValue as List <Injection3>, valueIsDict, inj.IsFolded);
                    }
                    else if (typeof(T) == typeof(Injection3))
                    {
                        Injection3 inj = injection as Injection3;
                        if (!(newValue is List <Injection2>))
                        {
                            newValue = new List <Injection2>();
                        }
                        inj.IsFolded = DrawArrayValue(newValue as List <Injection2>, valueIsDict, inj.IsFolded);
                    }
                    else if (typeof(T) == typeof(Injection2))
                    {
                        Injection2 inj = injection as Injection2;
                        if (!(newValue is List <Injection1>))
                        {
                            newValue = new List <Injection1>();
                        }
                        inj.IsFolded = DrawArrayValue(newValue as List <Injection1>, valueIsDict, inj.IsFolded);
                    }
                    else if (typeof(T) == typeof(Injection1))
                    {
                        Injection1 inj = injection as Injection1;
                        if (!(newValue is List <Injection>))
                        {
                            newValue = new List <Injection>();
                        }
                        inj.IsFolded = DrawArrayValue(newValue as List <Injection>, valueIsDict, inj.IsFolded);
                    }
                }
                else
                {
                    newValue = DrawValue <T>(injection.Type, value);
                }
                if ((newValue != null && value != null) ? newValue.GetHashCode() != value.GetHashCode() : newValue != value)
                {
                    injection.Value = newValue;
                }
                realIndex++;
            }

            GUILayout.EndHorizontal();

            if (injection.Type == InjectionType.List || injection.Type == InjectionType.Dict)
            {
                if (injection is IFoldable)
                {
                    IFoldable foldable = injection as IFoldable;
                    if (foldable.IsFolded)
                    {
                        GUI.backgroundColor = oldColor;
                        GUILayout.Space(-2F);
                    }
                }
            }

            if (remove)
            {
                array.RemoveAt(index);
                index--;
            }
            else if (up)
            {
                array[index]     = array[index - 1];
                array[index - 1] = injection;
            }
            else if (down)
            {
                array[index]     = array[index + 1];
                array[index + 1] = injection;
            }
            else
            {
                array[index] = injection;
            }
        }
        return(array);
    }