Все элементы из ToggleGroup в виде GameObject

95
17 мая 2021, 03:50

Из ToggleGroup мне нужно получить все элементы, но не в виде Toggle а в виде GameObject. Какие варианты решения есть для этой задачи?

Answer 1

Короткий ответ

Это невозможно, потому что список всех Toggle приватный (и это логично для полей, но публичного доступа к этому списку нет), в чем мы можем убедиться из исходного кода:

public class ToggleGroup : UIBehaviour
{
    ... 
    private List<Toggle> m_Toggles = new List<Toggle>();
    ...
}

Длинный ответ

Это возможно благодаря рефлексии, имя поля мы уже знаем, осталось только написать, к примеру, расширение для ToggleGroup'а:

using System;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using UnityEngine;
using UnityEngine.UI;

public static class ToggleGroupExtensions {
    private static FieldInfo _toggleListMember;
    public static IList<Toggle> GetToggles(this ToggleGroup grp) {
        if (_toggleListMember == null) {
            _toggleListMember = typeof(ToggleGroup).GetField("m_Toggles", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
            if (_toggleListMember == null)
                throw new Exception("Reflection error, Unity ToggleGroup source code might have been changed");
        }
        return new ReadOnlyCollection<Toggle>((IList<Toggle>)_toggleListMember.GetValue(grp));
    }
    public static List<GameObject> GetTogglesGameobjects(this ToggleGroup grp) {
        var toggles = grp.GetToggles();
        var gameObjects = new List<GameObject>(toggles.Count);
        gameObjects.AddRange(toggles.Select(x => x.gameObject));
        return gameObjects;
    }
}

P.S.

Вся логика рефлексии кэшируется в FieldInfo, так что этот подход не сильно отличен по производительности от прямого доступа к полю объекта класса, да и альтернатив в данном случае нет.

И да, из GetToggles важно возвращать именно ReadOnlyCollection, потому что изменение этого списка извне приведет к ошибкам логики ToggleGroup'а.

READ ALSO
CA1707 vs IDE0060

CA1707 vs IDE0060

Предупреждение CA1707 говорит:

127
Граница с эффектом у окна C# WPF

Граница с эффектом у окна C# WPF

Подскажите пожалуйста, как сделать границу окна, как у Visual Studio 2017

122
Контейнеризация темплейта aspnetcore-react

Контейнеризация темплейта aspnetcore-react

Недавно начал работать с реактом, решил попробовать реализовать SPA, воспользовавшись темплейтом aspnetcore-react

296
Обмен сообщениями между потоками

Обмен сообщениями между потоками

у меня есть сервер, который создает отдельный поток для каждого клиента

114