폴백 경로
Roslyn 생성 플랜·팩토리가 없을 때 런타임은 리플렉션·Expression 기반 경로로 동작합니다.
기능은 유지되지만 첫 빌드 비용·IL2CPP 제약이 커질 수 있습니다.
필드 세터: CreateSetter
생성 플랜이 없는 타입에 대해 GetGlobalInjectFields / GetSceneInjectFields는 처음 조회 시 다음을 수행합니다.
-
상속 체인을 따라 인스턴스 필드를 모읍니다(
GetAllInstanceFields). -
각
[GlobalInject]/[SceneInject]에 대해CreateSetter(field)로Action<object, object>를 만듭니다.
CreateSetter 내부 :
-
기본:
Expression으로 필드 대입 람다를 만들고Compile()합니다. -
예외 발생 시(AOT/IL2CPP 등에서 컴파일 실패 포함):
(t,v) => field.SetValue(t, v)로 폴백합니다.
한 번 만들어진 리스트는 _globalInjectCache / _sceneInjectCache 에 넣어 이후 조회는 캐시 히트입니다.
비용은 주로 타입당 첫 호출에 몰립니다.
생성자: GetInjectableConstructor + Invoke
CreateAndInject에서 TryGetGeneratedFactory가 실패하면:
-
GetInjectableConstructor로ConstructorInfo를 고릅니다(결과는_constructorCache에 센티넬 포함 저장). -
파라미터마다
resolver로 의존성을 채우고ctor.Invoke(args)합니다.
이 경로는 항상 리플렉션 생성이므로 IL2CPP에서는 스트리핑과 맞물립니다.
세이프티 넷(성능 부가 복잡도)
MasterInstaller / SceneInstaller의 ResolveByKey 는 첫 미스에서 Rebuild*RegistryCore 를 한 번 호출한 뒤,
다시 조회할 수 있습니다.
- 정상 히트 위주 프로젝트에서는 거의 타지 않습니다.
- 연속 미스에는 두 번째부터 재구성을 하지 않아 무한 루프를 피합니다.
도메인 리로드
TypeDataCache는 SubsystemRegistration 에서 정적 캐시 전부를 비웁니다.
에디터에서 도메인 리로드를 끈 경우 등 특수 환경에서는 캐시 정책을 염두에 두면 됩니다.
Enter Play Mode Custom을 시도하십시오.
해당 부근에서 로슬린 컴파일 및 요구 컴파일만 활성화 하면 정상 작동합니다.
현재는 안전망만 도입되어 있습니다.
정리
| 폴백 | 언제 | 특징 |
|---|---|---|
| Expression → SetValue | 세터 생성 실패 시 | IL2CPP에서 Compile 실패 가능 |
| 필드 플랜 없음 | partial/제너레이터 미적용 | 타입별 첫 조회 비용↑ |
ConstructorInfo.Invoke | 팩토리 플랜 없음 | Create<T> IL2CPP 취약 |
| 세이프티 넷 | 레지스트리 미스 1회 | 1회 재빌드 비용 |
폴백 가드(Diagnostics)가 플레이 직전에 같은 조건을 경고하는 이유와 연결됩니다.