결국 인터페이스를 만들수 없었다는 슬픈 이야기


따로 블로그도 안하니 여기다가 붙여본다



using System;

using System.Reflection;

using UnityEngine;


/*

//사용 방법

public class TestClass

{

    // Factory를 이용하려면 생성자는 nonpublic이어야 한다.

    TestClass() { }    

    bool Initialize(int a, float b, string c)

    {

        // false를 리턴하면 실패하고 null 이 결과값으로 전달된다

        return true;

    }

}

//생성

TestClass t = Factory.Create<TestClass>(0, 1.2f, "");

*/


/// <summary>

/// 매개변수의 유효성을 검사하고 유효하지 않으면 인스턴스를 생성시키지 않기 위해서 정적 팩토리 메소드를 사용한다.

/// 리플렉션을 사용하여 매 프레임마다 쓰면 느리기에 로딩 및 초기화시에만 사용합시다.

/// 생성자를 private로 선언해야 합니다

/// </summary>

public static class Factory

{

    public static T Create<T>(params object[] args) where T : class

    {

        T instance = null;

        try

        {

            instance = (T)Activator.CreateInstance(typeof(T), BindingFlags.Instance | BindingFlags.NonPublic, null, null, null);


            // 매개변수 타입 배열 생성

            Type[] argTypes = Array.ConvertAll(args, arg => arg.GetType());


            // Initialize 메소드 호출

            MethodInfo initializeMethod = typeof(T).GetMethod("Initialize", BindingFlags.Instance | BindingFlags.NonPublic, null, argTypes, null);

            if (initializeMethod == null)

            {

                Debug.Assert(false, $"Initialize 메소드를 찾을 수 없습니다: {typeof(T)}");

                return null;

            }


            if ((bool)initializeMethod.Invoke(instance, args) == false)

            {

                Debug.Assert(false, $"Factory::Create<{typeof(T)}> 생성실패!!");

                return null;

            }

        }

        catch (MissingMethodException)

        {

            Debug.Assert(false, $"{typeof(T)}의 생성자를 private로 선언해야 합니다.");

        }

        catch (Exception ex)

        {

            Debug.LogException(ex);

        }


        return instance; // 객체 생성 성공

    }

}



using FluffyDuck.Util;

using System.Reflection;

using System.Threading.Tasks;

using System;

using UnityEngine;


/*

// 사용 방법

public class TestClass : MonoBehaviour

{

    bool Initialize(int a, float b, string c)

    {

        // false를 리턴하면 실패하고 null 이 결과값으로 전달된다

        return true;

    }

}


// 생성

MBFactory.Create<TestClass>("Assets/프리팹키", Transform, (TestClass t) => { }, 0, 1.2f, "");

*/


/// <summary>

/// FactoryCore의 MonoBehaviour 버전

/// </summary>

public abstract class MBFactory

{

    static T CreateInstance<T>(GameObject obj, params object[] args) where T : MonoBehaviour

    {

        T instance = obj.GetComponent<T>();


        // 매개변수 타입 배열 생성

        Type[] argTypes = Array.ConvertAll(args, arg => arg.GetType());


        // Initialize 메소드 호출

        MethodInfo initializeMethod = typeof(T).GetMethod("Initialize", BindingFlags.Instance | BindingFlags.NonPublic, null, argTypes, null);

        if (initializeMethod == null)

        {

            Debug.Assert(false, $"Initialize 메소드를 찾을 수 없습니다: {typeof(T)}");

            return null;

        }


        try

        {

            if ((bool)initializeMethod.Invoke(instance, args) == false)

            {

                Debug.Assert(false, $"MBFactoryCore::Create<{typeof(T)}> 생성 실패!!");

                GameObject.Destroy(obj);

                return null;

            }

        }

        catch (TargetException e)

        {

            Debug.Assert(false, $"생성한 프리팹에 {typeof(T)} 컴포넌트가 붙어 있는지 확인해보세요.");

            Debug.LogException(e);

        }

        catch (Exception e) { Debug.LogException(e); }


        return instance;

    }


    public static void Create<T>(string path, Transform parent, Action<T> cb, params object[] args) where T : MonoBehaviour

    {

        try

        {

            GameObjectPoolManager.Instance.GetGameObject(path, parent, (GameObject obj) =>

            {

                T instance = CreateInstance<T>(obj, args);


                cb?.Invoke(instance);

            });

        }

        catch (Exception e)

        {

            Debug.Assert(false, e.ToString());

        }

    }


    public async static Task<T> CreateAsync<T>(string path, Transform parent, params object[] args) where T : MonoBehaviour

    {

        try

        {

            var obj = await GameObjectPoolManager.Instance.GetGameObjectAsync(path, parent);

            return CreateInstance<T>(obj, args);

        }

        catch (Exception e)

        {

            Debug.Assert(false, e.ToString());

            return null;

        }

    }

}