Zenject 배우기 3-2) 컨스트럭션 메서드 (Construction Methods)

 

3-1) 에서 살펴보았던 종속성 맵핑 메서드 중 ConstructionMethod 부분에 대해 따로 알아보자.

이전 예제에서 4번째 줄은 실제 메서드 이름이 아닌 분류 명칭일 뿐이고,

해당 위치에 Construction Method가 필요하다고 표시한 것이다.

Container.Bind<ContractType>()
    .WithId(Identifier)
    .To<ResultType>()
    .FromConstructionMethod() // 이것!
    .AsScope()
    .WithArguments(Arguments)
    .OnInstantiated(InstantiatedCallback)
    .When(Condition)
    .(Copy|Move)Into(All|Direct)SubContainers()
    .NonLazy()
    .IfNotBound();

 

1. FromNew

- C#의 new 연산자로 생성하여 바인딩한다.

- 바인딩의 기본 설정이라 Construction Method를 명시하지 않았다면 자동으로 FromNew으로 선택된다.

Container.Bind<Foo>();
Container.Bind<Foo>().FromNew(); // 윗 줄의 코드와 같다.

 

2. FromInstance

- 인자로 직접 객체를 넘겨 바인딩한다.

Container.Bind<Foo>().FromInstance(new Foo());

// 타입을 생략하면 대신 BindInstance를 사용할 수도 있다.
Container.BindInstance(new Foo());
Container.BindInstance(5.13f);
Container.BindInstance("foo");

// 여러개의 인스턴스들을 넘기는 것도 가능하다.
Container.BindInstances(5.13f, "foo", new Foo());

 

3. FromMethod / FromMethodMultiple

- 메서드를 사용하여 바인딩한다.

Container.Bind<Foo>().FromMethod(SomeMethod);

Foo SomeMethod(InjectContext context)
{
    return new Foo();
}

// 여러개의 인스턴스를 넘길 경우 IEnumerable<T> 를 사용하면 된다. 
IEnumerable<Foo> GetFoos(InjectContext context)
{
    return new Foo[]{ new Foo(), new Foo(), new Foo() }
}

 

4. FromFactory / FromIFactory

- Zenject.IFactory<T> 인터페이스를 구현하는 클래스를 만들넘겨줘서 바인딩한다.

- IFactory 인터페이스는 T를 반환하는 Create() 메서드 한개만 구현하도록 되어있다. 

- FromMethod와 유사하지만 IFactory를 구현한 클래스 자체도 의존성 주입이 가능한 장점이 있다고 한다.

- FromIFactory는 좀 더 자유롭게 식을 구성 가능하다.

class FooFactory : IFactory<Foo>
{
    public Foo Create()
    {
        return new Foo();
    }
}

Container.Bind<Foo>().FromFactory<FooFactory>()
class FooFactory : ScriptableObject, IFactory<Foo>
{
    public Foo Create()
    {
        return new Foo();
    }
}

Container.Bind<Foo>().FromIFactory(x => x.To<FooFactory>()
                     .FromScriptableObjectResource("FooFactory"))
                     .AsSingle();

아래 두 코드는 결과가 같다.

Container.Bind<Foo>().FromFactory<FooFactory>().AsSingle();
Container.Bind<Foo>().FromIFactory(x => x.To<FooFactory>().AsCached()).AsSingle();

 

5. FromComponentInNewPrefab

- 넘겨 받은 프리팹으로 새로운 게임 오브젝트를 생성한 뒤, 주입한다.

- 프리팹이기 때문에 ResultType은 반드시 UnityEngine.MonoBehaviour 혹은 UnityEngine.Component를 구현해야 한다. 

- 만족하는 타입이 여러개라면 가장 처음으로 타입이 일치하는 것을 사용한다. 때문에 최대한 구체적인 타입에 바인딩을 하자.

Container.Bind<Foo>().FromComponentInNewPrefab(somePrefab);

 

6. FromComponentInNewPrefabResource

- FromComponentInNewPrefab과 동일하지만 리소스 폴더의 경로를 넘겨받는다.

Container.Bind<Foo>().FromComponentInNewPrefabResource("Some/Path/Foo");

 

7. FromComponentsInNewPrefab / FromComponentsInNewPrefabResource

- 각각 s가 붙어 복수의 할당이 가능한 버전. 

- List<ContractType> 같은 곳에 주입할 수 있다. 

 

8. FromNewComponentOnNewGameObject / FromNewComponentOnNewPrefab

- (빈 게임 오브젝트/할당한 프리팹)를 생성하고, 이 오브젝트에 주어진 타입의 컴포넌트를 붙인다.

- ResultType은 반드시 UnityEngine.MonoBehaviour 혹은 UnityEngine.Component를 구현해야 한다. 

Container.Bind<Foo>().FromNewComponentOnNewGameObject();
Container.Bind<Foo>().FromNewComponentOnNewPrefab(somePrefab);

 

9. FromNewComponentOnNewPrefabResource

- FromNewComponentOnNewPrefab과 동일하지만 리소스 폴더의 경로를 넘겨받는다.

Container.Bind<Foo>().FromNewComponentOnNewPrefabResource("Some/Path/Foo");

 

10. FromNewComponentOn

- 인자로 넘겨준 게임오브젝트에 ResultType 컴포넌트를 붙인다. 

Container.Bind<Foo>().FromNewComponentOn(someGameObject);

 

11. FromNewComponentSibling

- 현재 transform에 ResultType 컴포넌트를 붙인다.

- 주의! 이미 컴포넌트가 있다면, 새로 생성하지않고 이미 붙어있는 컴포넌트를 리턴한다.

- RequireComponent 어트리뷰트와 비슷하게 동작한다.

Container.Bind<Foo>().FromNewComponentSibling();

 

12. FromComponentInHierarchy / FromComponentsInHierarchy

- 하이어라키에서 하위의 오브젝트들에서 재귀탐색하여 가장 최초로 발견되는 컴포넌트를 찾는다.

- 씬 컨텍스트라면 모든 오브젝트를 탐색하니 유니티의 FindObjectByType 함수들과 같이 성능문제가 있다.

Container.Bind<Foo>().FromComponentInHierarchy().AsSingle();

 

13. FromComponentSibling

- 현재 transform에 붙어있는 컴포넌트를 검색한다.

- GetComponent와 비슷하게 동작한다.

Container.Bind<Foo>().FromComponentSibling();

 

14. FromComponentInParents / FromComponentsInParents

- 현재 transform이나 부모 transform에 붙어있는 컴포넌트를 검색한다.

Container.Bind<Foo>().FromComponentInParents();

 

15. FromComponentInChildren / FromComponentsInChildren 

- 현재 transform이나 자식 transform에 붙어있는 컴포넌트를 검색한다.

Container.Bind<Foo>().FromComponentInChildren();

 

16. FromNewComponentOnRoot 

- 주어진 ResultType의 컴포넌트를 Root에 붙인다.

Container.Bind<Foo>().FromNewComponentOnRoot();

 

17. FromResource / FromResources

- ResultType을 리소스 폴더에서 불러온다.

- 컴포넌트 제한이 아니라 텍스쳐나, 사운드, 프리팹 등 여러 타입 등이 가능하다.

Container.Bind<Texture>().WithId("Glass").FromResource("Some/Path/Glass");

 

18. FromScriptableObjectResource

- 리소스 경로에 있는 ScritableObject를 바인딩한다.

- 에디터에서 SO의 값을 바꾸면 원본 값이 보존되지 않기 때문에, 원본을 보존하고 싶다면 FromNewScriptableObjectResource를 사용하자.

public class Foo : ScriptableObject
{
}

Container.Bind<Foo>().FromScriptableObjectResource("Some/Path/Foo");

 

19. FromNewScriptableObjectResource

- FromScriptableObjectResource과 동일하지만, 카피본을 만들어서 사용한다.

 

20. FromResolve / FromResolveAll 

- 다른 컨테이너로부터 인스턴스를 가져온다. ( DiContainer.Resolve<ResultType>() )

- 주의! ResultType이 별도의 Bind 문에서 분리되어 바인딩 되어야 동작한다. 

public interface IFoo
{
}

public interface IBar : IFoo
{
}

public class Foo : IBar
{
}

Container.Bind<IFoo>().To<IBar>().FromResolve();
Container.Bind<IBar>().To<Foo>();

 

21. FromResolveGetter<ObjectType> / FromResolveAllGetter<ObjectType>

- 다른 바인딩을 통해 얻은 종속성의 속성을 사용하여 인스턴스를 가져온다. ( DiContainer.Resolve<ObjectType>() )

- 주의! ObjectType이 별도의 Bind 문에서 분리되어 바인딩 되어야 동작한다. 

public class Bar
{
}

public class Foo
{
    public Bar GetBar()
    {
        return new Bar();
    }
}

Container.Bind<Foo>();
Container.Bind<Bar>().FromResolveGetter<Foo>(x => x.GetBar());

 

22. FromSubContainerResolve / FromSubContainerResolveAll

- 하위 컨테이너들에서 ResultType을 얻는다.

- 주의! 서브 컨테이너들이 ResultType을 바인딩하고 있는 경우에만 동작한다.

- 추가적으로 다음과 같은 메서드들과 조합하여 사용한다.

ByNewPrefabMethod, ByNewPrefabInstaller, ByNewPrefabResourceMethod, ByNewPrefabResourceInstaller, ByNewGameObjectInstaller, ByNewGameObjectMethod

, ByMethod, ByInstaller, ByNewContextPrefab, ByNewContextPrefabResource,ByInstance

 

ByNewPrefabMethod의 예시

- 프리팹을 생성하고, 이를 사용하여 컨테이너를 초기화합니다.

Container.Bind<Foo>().FromSubContainerResolve().ByNewPrefabMethod(MyPrefab, InstallFoo);

void InstallFoo(DiContainer subContainer)
{
    subContainer.Bind<Foo>();
}

 

 

 

'Unity 연구 > Zenject' 카테고리의 다른 글

Zenject 배우기 3-1) 바인딩  (0) 2021.09.05
Zenject 배우기 2) 주입  (0) 2021.09.05
Zenject 배우기 1) 기본 소개  (1) 2021.08.29

댓글

Designed by JB FACTORY