### **팩토리 등록 (Registering Factories)** - **필요성:** VContainer는 일반적으로 등록된 의존성을 처음 해결할 때 구성합니다(이미 등록된 인스턴스는 제외). 만약 의존성 생성 시점에 대해 더 세밀한 제어가 필요하다면, 팩토리 함수를 등록하고 사용할 수 있습니다. - **정의:** 팩토리 함수는 다른 의존성처럼 해결되는 `Func<>` 델리게이트입니다. 이들은 언제든지 하나 이상의 다른 의존성을 생성하는 데 사용될 수 있습니다. **참고:** 팩토리가 "생성"을 의미하는 이름에도 불구하고, 새로운 객체를 생성하는 대신 기존 객체를 반환할 수도 있습니다. 이는 동일한 타입의 여러 의존성을 다른 키에 매핑할 때 유용할 수 있습니다(예: 로컬 멀티플레이어 게임에서 각 플레이어에 대한 고유한 컨트롤러 서비스). **기본 팩토리 예시:** C# ``` class FooFactory { // 생성자 주입을 통해 의존성(DependencyA)을 받음 public FooFactory (DependencyA dependencyA) { this.dependencyA = dependencyA; } // Foo 객체를 생성하는 메서드 public Foo Create(int b) => new Foo(b, dependencyA); } // 등록 builder.Register<FooFactory>(Lifetime.Singleton); // FooFactory 자체를 컨테이너에 등록 // 사용 var factory = container.Resolve<FooFactory>(); // 의존성 해결은 여기서 발생 var foo1 = factory.Create(1); // 여기서 새로운 Foo 객체가 생성되며, 추가적인 의존성 해결은 필요 없음 var foo2 = factory.Create(2); var foo3 = factory.Create(3); ``` - **설명:** `FooFactory`는 `DependencyA`에 의존하며, `Create` 메서드를 통해 `Foo` 객체를 생성합니다. `FooFactory`는 컨테이너에 `Singleton`으로 등록되어 한 번만 생성됩니다. `Create` 메서드가 호출될 때는 VContainer의 의존성 해결이 다시 발생하지 않고, `FooFactory`가 이미 주입받은 `dependencyA`를 활용하여 `Foo` 객체를 생성합니다. **런타임 의존성 주입을 포함하는 팩토리:** 팩토리 내부에서 `IObjectResolver` API를 명시적으로 사용하여 런타임에 다른 의존성을 해결할 수도 있습니다. C# ``` builder.Register<IFooFactory>(container => { // 이 람다 함수는 IFooFactory가 처음 해결될 때 한 번 실행됩니다. // 여기서 IFooFactory 인스턴스가 생성됩니다. return new FooFactoryWithRuntimeDeps(container.Resolve<SomeOtherDependency>()); }, Lifetime.Singleton); class FooFactoryWithRuntimeDeps : IFooFactory { private readonly SomeOtherDependency _someOtherDependency; public FooFactoryWithRuntimeDeps(SomeOtherDependency someOtherDependency) { _someOtherDependency = someOtherDependency; } public IFoo CreateFoo(int id) { // 런타임에 필요한 다른 의존성을 여기서 Resolve할 수 있습니다. // 예를 들어, 매번 다른 설정을 가진 Foo를 생성하고 싶을 때 유용합니다. // 하지만 이 방식은 Resolve가 런타임에 발생하므로 성능에 영향을 줄 수 있습니다. // 가능한 한 생성자 주입을 통해 의존성을 미리 주입받는 것이 좋습니다. return new Foo(id, _someOtherDependency.GetDataForFoo(id)); } } ``` - **설명:** 델리게이트를 통해 `IFooFactory`를 등록합니다. 이 델리게이트는 `IObjectResolver`를 인자로 받아 `SomeOtherDependency`를 해결하고, 이를 사용하여 `FooFactoryWithRuntimeDeps`를 생성합니다. 이렇게 생성된 팩토리는 `CreateFoo` 메서드 내부에서 추가적인 런타임 의존성 해결 로직을 가질 수 있습니다. **제네릭 팩토리 (Generic Factory):** 동적으로 다양한 타입의 객체를 생성해야 할 때 제네릭 팩토리를 사용할 수 있습니다. C# ``` // 캐릭터 타입에 따라 다른 CharacterActor를 생성하는 팩토리 builder.Register<Func<CharacterType, CharacterActor>>(container => { return characterType => { GameObject characterPrefab; // characterType에 따라 다른 프리팹 선택 로직 if (characterType == CharacterType.Warrior) { characterPrefab = warriorPrefab; } else { characterPrefab = magePrefab; } // IObjectResolver.Instantiate를 사용하여 프리팹을 인스턴스화하고 의존성 주입 return container.Instantiate(characterPrefab, parentTransform); }; }, Lifetime.Scoped); ``` - **설명:** `Func<CharacterType, CharacterActor>` 타입의 팩토리를 등록합니다. 이 팩토리는 `CharacterType`을 입력받아 적절한 프리팹을 선택하고, `container.Instantiate`를 사용하여 `CharacterActor` 인스턴스를 생성하며 자동으로 의존성을 주입합니다. **팩토리 메서드 등록 (Registering factory methods):** 클래스 내부에 정의된 팩토리 메서드를 `Func<>` 델리게이트처럼 컨테이너에 등록할 수 있습니다. C# ``` class FooFactory { readonly DependencyA dependencyA; public FooFactory (DependencyA dependencyA) { this.dependencyA = dependencyA; } public Foo Create(int b) => new Foo (b, dependencyA); } builder.Register<FooFactory>(Lifetime.Singleton); // FooFactory 자체를 등록 // FooFactory의 Create 메서드를 Func<int, Foo> 델리게이트로 등록 builder.RegisterFactory(container => container.Resolve<FooFactory>().Create, Lifetime.Singleton); // 사용 var factory = container.Resolve<Func<int, Foo>>(); // 팩토리 델리게이트를 가져옴 var foo1 = factory(1); var foo2 = factory(2); var foo3 = factory(3); var originalFactoryObject = container.Resolve<FooFactory>(); // 필요하다면 원본 팩토리 객체도 가져올 수 있음 // 만약 FooFactory가 IDisposable을 구현했다면, IObjectResolver가 Dispose될 때 Dispose()가 호출됩니다. ``` - **설명:** `FooFactory` 클래스를 등록한 후, `RegisterFactory`를 사용하여 `FooFactory` 인스턴스의 `Create` 메서드를 `Func<int, Foo>` 타입으로 컨테이너에 등록합니다. 이렇게 하면 외부에서 `FooFactory` 클래스 자체에 대한 지식 없이도 `Func<int, Foo>` 델리게이트를 주입받아 `Foo` 객체를 생성할 수 있습니다. ### 요약 VContainer에서 팩토리를 사용하여 의존성 객체 생성을 동적으로 제어하는 다양한 방법을 제시합니다. 여기에는 `Func<>` 델리게이트를 사용한 기본 팩토리, `IObjectResolver`를 활용하여 런타임 의존성을 주입하는 팩토리, 제네릭 팩토리, 그리고 기존 클래스의 메서드를 팩토리로 등록하는 방법이 포함됩니다. 팩토리는 특히 게임에서 프리팹 인스턴스화나 동적인 객체 생성 로직이 필요한 경우에 강력한 패턴으로 활용될 수 있습니다. --- 이전 : [[4.2 Register using delegate]] | 다음 : [[4.4 Register MonoBehaviour]]