うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【C#】Stateを管理するクラス

State を enum で分けて管理しているとき クラスが増えていった際に
追加処理が面倒だったので自動的に管理してくれるものを作成

using System;
using System.Collections.Generic;
using System.Linq;
 
public class ClassManage<T, TEnum> where T : BaseClass where TEnum : struct
{
    private readonly Dictionary<int, T> _classes;
 
    public T this[TEnum type]
    {
        get
        {
            if (!_classes.ContainsKey(type.GetHashCode()))
                throw new Exception("Invalid Type");

            return _classes[type.GetHashCode()];
        }
    }
 
    public ClassManage()
    {
        _classes = new Dictionary<int, T>();
 
        var classTypes = typeof(T).Assembly.GetTypes()
            .Where(t => t.IsSubclassOf(typeof(T)));
 
        foreach(var type in classTypes)
        {
            var instance = Activator.CreateInstance(type) as T;
            _classes.Add((int)instance.Type, instance);
        }
    }
}

サンプル

その Class がどの enumに紐付いている かを管理するベースクラスを用意します ※今回はどのクラスか分けるように Display メソッドを追加しています

public abstract class BaseClass
{
    public abstract ClassType Type { get; }

    public abstract void Display();
}

各クラスはこのようになります

public enum ClassType
{
    A,
    B,
}

public class ClassA : BaseClass
{
    public override ClassType Type => ClassType.A;

    public override void Display()
    {
        Debug.Log("ClassA");
    }
}

public class ClassB : BaseClass
{
    public override ClassType Type => ClassType.B;

    public override void Display()
    {
        Debug.Log("ClassB");
    }
}

テスト

このように this アクセスをすることでそのクラスにアクセスできます

using System;
using UnityEngine;

public class SampleMonoBehaviour : MonoBehaviour
{
    private ClassManage<BaseClass, ClassType> _manage;
 
    private void Awake()
    {
        _manage = new ClassManage<BaseClass, ClassType>();

        _manage[ClassType.A].Display();
        _manage[ClassType.B].Display();
    }
}