#Is anybody here familiar with Zenject
1 messages · Page 1 of 1 (latest)
@neon lake Awesome!
So, I'm working in a model-view-presenter paradigm. I pass the model to a factory to create (instantiate) the corresponding presenter from a prefab. I want to execute an OnInstantiated callback once the factory creates the object. So I typically do as follows:
public class FooModel { }
public class FooPresenter : MonoBehaviour
{
public class Factory : PlaceholderFactory<FooModel, FooPresenter> { }
}
public class FooInstaller : MonoInstaller
{
[SerializeField] FooPresenter _fooPrefab;
public override void InstallBindings()
{
Container.BindFactory<FooModel, FooPresenter, FooPresenter.Factory>()
.FromComponentInNewPrefab(_fooPrefab)
.OnInstantiated<FooPresenter>(OnFooPresenterInstantiated);
}
void OnFooPresenterInstantiated(InjectContext context, FooPresenter presenter)
{
// Do something
}
}
The above is all fine and dandy. However, what I'd like to do now is the same as above, BUT, I have 2 (or more) prefabs, each having their own unique MonoBehaviour. Those 2 (or more) MonoBehaviours derive from the same abstract base class. I want the factory to determine which prefab to use based on an enum type in the corresponding model.
This is so far the best way I've been able to do this.
I'm just wondering if there is a cleaner, simpler solution.
Thanks in advance!
public enum FooType { A, B }
public class FooModel
{
public FooType Type { get; set; }
}
public abstract class FooPresenter : MonoBehaviour
{
public class Factory : PlaceholderFactory<FooModel, FooPresenter> { }
}
public class FooPresenterA : FooPresenter { }
public class FooPresenterB : FooPresenter { }
public class FooPresenterFactory : IFactory<FooModel, FooPresenter>
{
[Inject] readonly FooPresenterA _fooPrefabA;
[Inject] readonly FooPresenterB _fooPrefabB;
[Inject] readonly DiContainer _container;
[Inject] readonly Action<InjectContext, FooModel> _onCreate;
public FooPresenter Create(FooModel model)
{
var prefab = ResolveFooPrefab(model.Type);
var presenter = _container.InstantiatePrefabForComponent<FooPresenter>(prefab);
var injectContext = new InjectContext(_container, typeof(FooPresenter));
_onCreate.Invoke(injectContext, model);
return presenter;
}
FooPresenter ResolveFooPrefab(FooType fooType)
{
switch (fooType)
{
case FooType.A: return _fooPrefabA;
case FooType.B: return _fooPrefabB;
default: throw new ArgumentOutOfRangeException();
}
}
}
public class FooInstaller : MonoInstaller
{
[SerializeField] FooPresenterA _fooPrefabA;
[SerializeField] FooPresenterB _fooPrefabB;
public override void InstallBindings()
{
Container.Bind<FooPresenterA>()
.FromInstance(_fooPrefabA)
.AsSingle()
.WhenInjectedInto<FooPresenterFactory>();
Container.Bind<FooPresenterB>()
.FromInstance(_fooPrefabB)
.AsSingle()
.WhenInjectedInto<FooPresenterFactory>();
Container.BindFactory<FooModel, FooPresenter, FooPresenter.Factory>()
.FromIFactory(x => x.To<FooPresenterFactory>()
.AsSingle()
.WithArguments(OnInstantiateFooPresenter()));
}
Action<InjectContext, FooModel> OnInstantiateFooPresenter() => (context, model) =>
{
// Do something
};
}