Skip to content

Commit

Permalink
Add UseComponents with specific parent
Browse files Browse the repository at this point in the history
  • Loading branch information
hadashiA committed Feb 10, 2021
1 parent bf18d70 commit 25c2ff9
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 70 deletions.
8 changes: 8 additions & 0 deletions VContainer/Assets/VContainer/Runtime/Interfaces.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ Component InstantiatePrefab(IObjectResolver resolver)
{
destination.Prefab.gameObject.SetActive(false);
}
var component = UnityEngine.Object.Instantiate(destination.Prefab, parent);

var component = parent != null
? UnityEngine.Object.Instantiate(destination.Prefab, parent)
: UnityEngine.Object.Instantiate(destination.Prefab);

injector.Inject(component, resolver, Parameters);
component.gameObject.SetActive(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,44 @@ public void OnException(Action<Exception> exceptionHandler)
public readonly struct ComponentsBuilder
{
readonly IContainerBuilder containerBuilder;
readonly Transform parentTransform;

public ComponentsBuilder(IContainerBuilder containerBuilder)
public ComponentsBuilder(IContainerBuilder containerBuilder, Transform parentTransform = null)
{
this.containerBuilder = containerBuilder;
this.parentTransform = parentTransform;
}

public RegistrationBuilder AddInstance(MonoBehaviour component)
=> containerBuilder.RegisterComponent(component);
public RegistrationBuilder AddInstance(Component component)
{
return containerBuilder.RegisterComponent(component);
}

public RegistrationBuilder AddInHierarchy<T>() where T : Component
=> containerBuilder.RegisterComponentInHierarchy<T>();
{
var registrationBuilder = containerBuilder.RegisterComponentInHierarchy<T>();
if (parentTransform != null)
registrationBuilder.UnderTransform(parentTransform);
return registrationBuilder;
}

public ComponentRegistrationBuilder AddOnNewGameObject<T>(Lifetime lifetime, string newGameObjectName = null)
where T : Component
=> containerBuilder.RegisterComponentOnNewGameObject<T>(lifetime, newGameObjectName);
{
var registrationBuilder = containerBuilder.RegisterComponentOnNewGameObject<T>(lifetime, newGameObjectName);
if (parentTransform != null)
registrationBuilder.UnderTransform(parentTransform);
return registrationBuilder;
}

public ComponentRegistrationBuilder AddInNewPrefab<T>(T prefab, Lifetime lifetime)
where T : Component
=> containerBuilder.RegisterComponentInNewPrefab(prefab, lifetime);
{
var registrationBuilder = containerBuilder.RegisterComponentInNewPrefab(prefab, lifetime);
if (parentTransform != null)
registrationBuilder.UnderTransform(parentTransform);
return registrationBuilder;
}
}

public static class ContainerBuilderUnityExtensions
Expand All @@ -61,16 +80,18 @@ public static void UseEntryPoints(
configuration(entryPoints);
}

public static void RegisterEntryPointExceptionHandler(
this IContainerBuilder builder,
Action<Exception> exceptionHandler)
public static void UseComponents(this IContainerBuilder builder, Action<ComponentsBuilder> configuration)
{
builder.RegisterInstance(new EntryPointExceptionHandler(exceptionHandler));
var components = new ComponentsBuilder(builder);
configuration(components);
}

public static void UseComponents(this IContainerBuilder builder, Action<ComponentsBuilder> configuration)
public static void UseComponents(
this IContainerBuilder builder,
Transform root,
Action<ComponentsBuilder> configuration)
{
var components = new ComponentsBuilder(builder);
var components = new ComponentsBuilder(builder, root);
configuration(components);
}

Expand All @@ -84,6 +105,13 @@ public static RegistrationBuilder RegisterEntryPoint<T>(this IContainerBuilder b
return registrationBuilder.AsImplementedInterfaces();
}

public static void RegisterEntryPointExceptionHandler(
this IContainerBuilder builder,
Action<Exception> exceptionHandler)
{
builder.RegisterInstance(new EntryPointExceptionHandler(exceptionHandler));
}

public static RegistrationBuilder RegisterComponent(this IContainerBuilder builder, MonoBehaviour component)
{
var registrationBuilder = builder.RegisterInstance(component);
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions VContainer/Assets/VContainer/Runtime/Unity/LifetimeScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ static LifetimeScope Create(IInstaller installer = null)
return newScope;
}

public static LifetimeScope Create(Action<IContainerBuilder> installation)
=> Create(new ActionInstaller(installation));
public static LifetimeScope Create(Action<IContainerBuilder> configuration)
=> Create(new ActionInstaller(configuration));

public static ParentOverrideScope EnqueueParent(LifetimeScope parent)
=> new ParentOverrideScope(parent);
Expand Down
137 changes: 83 additions & 54 deletions VContainer/Assets/VContainer/Tests/Unity/UnityContainerBuilderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ public void RegisterComponent()
[Test]
public void RegisterComponentInHierarchy()
{
var lifetimeScope = new GameObject("LifetimeScope").AddComponent<LifetimeScope>();
var go1 = new GameObject("Parent");
var go2 = new GameObject("Child A");
var go3 = new GameObject("Child B");
Expand All @@ -66,12 +65,13 @@ public void RegisterComponentInHierarchy()

go3.AddComponent<SampleMonoBehaviour>();

var builder = new ContainerBuilder { ApplicationOrigin = lifetimeScope };
builder.Register<ServiceA>(Lifetime.Transient);
builder.RegisterComponentInHierarchy<SampleMonoBehaviour>();
var lifetimeScope = LifetimeScope.Create(builder =>
{
builder.Register<ServiceA>(Lifetime.Transient);
builder.RegisterComponentInHierarchy<SampleMonoBehaviour>();
});

var container = builder.Build();
var resolved = container.Resolve<SampleMonoBehaviour>();
var resolved = lifetimeScope.Container.Resolve<SampleMonoBehaviour>();

Assert.That(resolved, Is.InstanceOf<SampleMonoBehaviour>());
Assert.That(resolved.ServiceA, Is.InstanceOf<ServiceA>());
Expand Down Expand Up @@ -122,68 +122,59 @@ public void RegisterComponentInHierarchyUnderTransform()
[Test]
public void RegisterComponentInHierarchyWithBuiltinType()
{
var lifetimeScope = new GameObject("LifetimeScope").AddComponent<LifetimeScope>();
var go1 = new GameObject("Parent");

go1.AddComponent<BoxCollider>();

var builder = new ContainerBuilder { ApplicationOrigin = lifetimeScope };
builder.Register<ServiceA>(Lifetime.Transient);
builder.RegisterComponentInHierarchy<BoxCollider>();

var container = builder.Build();
var resolved = container.Resolve<BoxCollider>();
var lifetimeScope = LifetimeScope.Create(builder =>
{
builder.Register<ServiceA>(Lifetime.Transient);
builder.RegisterComponentInHierarchy<BoxCollider>();
});

var resolved = lifetimeScope.Container.Resolve<BoxCollider>();
Assert.That(resolved, Is.InstanceOf<BoxCollider>());
}

[Test]
public void RegisterComponentOnNewGameObject()
{
{
var go1 = new GameObject("Parent");
var builder = new ContainerBuilder();
builder.Register<ServiceA>(Lifetime.Transient);
builder.RegisterComponentOnNewGameObject<SampleMonoBehaviour>(Lifetime.Transient, "hoge")
.UnderTransform(go1.transform);

var container = builder.Build();
var resolved1 = container.Resolve<SampleMonoBehaviour>();
var resolved2 = container.Resolve<SampleMonoBehaviour>();
var builder = new ContainerBuilder();
builder.Register<ServiceA>(Lifetime.Transient);
builder.RegisterComponentOnNewGameObject<SampleMonoBehaviour>(Lifetime.Scoped, "hoge");

Assert.That(resolved1.gameObject.name, Is.EqualTo("hoge"));
Assert.That(resolved2.gameObject.name, Is.EqualTo("hoge"));
Assert.That(resolved1, Is.InstanceOf<SampleMonoBehaviour>());
Assert.That(resolved2, Is.InstanceOf<SampleMonoBehaviour>());
Assert.That(resolved1.transform.parent, Is.EqualTo(go1.transform));
Assert.That(resolved2.transform.parent, Is.EqualTo(go1.transform));
Assert.That(resolved1, Is.Not.EqualTo(resolved2));
}
var container = builder.Build();
var resolved1 = container.Resolve<SampleMonoBehaviour>();
var resolved2 = container.Resolve<SampleMonoBehaviour>();
Assert.That(resolved1.gameObject.name, Is.EqualTo("hoge"));
Assert.That(resolved2.gameObject.name, Is.EqualTo("hoge"));
Assert.That(resolved1, Is.InstanceOf<SampleMonoBehaviour>());
Assert.That(resolved2, Is.InstanceOf<SampleMonoBehaviour>());
Assert.That(resolved1.transform.parent, Is.Null);
Assert.That(resolved2.transform.parent, Is.Null);
Assert.That(resolved1, Is.EqualTo(resolved2));
}

{
var builder = new ContainerBuilder();
builder.Register<ServiceA>(Lifetime.Transient);
builder.RegisterComponentOnNewGameObject<SampleMonoBehaviour>(Lifetime.Scoped, "hoge");
[Test]
public void RegisterComponentOnNewGameObjectUnderTransform()
{
var go1 = new GameObject("Parent");

var container = builder.Build();
var resolved1 = container.Resolve<SampleMonoBehaviour>();
var resolved2 = container.Resolve<SampleMonoBehaviour>();
Assert.That(resolved1.gameObject.name, Is.EqualTo("hoge"));
Assert.That(resolved2.gameObject.name, Is.EqualTo("hoge"));
Assert.That(resolved1, Is.InstanceOf<SampleMonoBehaviour>());
Assert.That(resolved2, Is.InstanceOf<SampleMonoBehaviour>());
Assert.That(resolved1.transform.parent, Is.Null);
Assert.That(resolved2.transform.parent, Is.Null);
Assert.That(resolved1, Is.EqualTo(resolved2));
}
{
var builder = new ContainerBuilder();
builder.Register<ServiceA>(Lifetime.Transient);
builder.RegisterComponentOnNewGameObject<SampleMonoBehaviour>(Lifetime.Scoped, "hoge");
var builder = new ContainerBuilder();
builder.Register<ServiceA>(Lifetime.Transient);
builder.RegisterComponentOnNewGameObject<SampleMonoBehaviour>(Lifetime.Transient, "hoge")
.UnderTransform(go1.transform);

var container = builder.Build();
Assert.That(container.Resolve<SampleMonoBehaviour>(), Is.InstanceOf<SampleMonoBehaviour>());
}
var container = builder.Build();
var resolved1 = container.Resolve<SampleMonoBehaviour>();
var resolved2 = container.Resolve<SampleMonoBehaviour>();

Assert.That(resolved1.gameObject.name, Is.EqualTo("hoge"));
Assert.That(resolved2.gameObject.name, Is.EqualTo("hoge"));
Assert.That(resolved1, Is.InstanceOf<SampleMonoBehaviour>());
Assert.That(resolved2, Is.InstanceOf<SampleMonoBehaviour>());
Assert.That(resolved1.transform.parent, Is.EqualTo(go1.transform));
Assert.That(resolved2.transform.parent, Is.EqualTo(go1.transform));
Assert.That(resolved1, Is.Not.EqualTo(resolved2));
}

[Test]
Expand Down Expand Up @@ -236,6 +227,44 @@ public void RegisterComponentInNewPrefab()
}
}

[Test]
public void UseComponentsWithParentTransform()
{
var go1 = new GameObject("Parent");
var go2 = new GameObject("Child A");
var go3 = new GameObject("Child B");

go3.transform.SetParent(go2.transform);
go2.transform.SetParent(go1.transform);

go1.AddComponent<SampleMonoBehaviour>();
go3.AddComponent<SampleMonoBehaviour>();

var lifetimeScope = LifetimeScope.Create(builder =>
{
builder.Register<ServiceA>(Lifetime.Scoped);
builder.Register<ServiceB>(Lifetime.Scoped);

builder.UseComponents(go2.transform, components =>
{
components.AddInHierarchy<SampleMonoBehaviour>();
});

builder.UseComponents(go3.transform, components =>
{
components.AddOnNewGameObject<SampleMonoBehaviour2>(Lifetime.Scoped);
});
});

var found = lifetimeScope.Container.Resolve<SampleMonoBehaviour>();
Assert.That(found, Is.InstanceOf<SampleMonoBehaviour>());
Assert.That(found.transform.parent, Is.EqualTo(go2.transform));

var created = lifetimeScope.Container.Resolve<SampleMonoBehaviour2>();
Assert.That(created, Is.InstanceOf<SampleMonoBehaviour2>());
Assert.That(created.transform.parent, Is.EqualTo(go3.transform));
}

[UnityTest]
public IEnumerator DispatchMonoBehaviour()
{
Expand Down
29 changes: 28 additions & 1 deletion website/docs/registering/register-monobehaviour.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ builder.UseComponents(components =>
components.AddInHierarchy<YourBehaviour>();
components.AddFromNewPrefab(prefab, Lifetime.Scoped);
components.AddOnNewGameObject<YourBehaviour>(Lifetime.Scoped, "name");
})
});
```

This is the same as:
Expand All @@ -95,6 +95,33 @@ builder.RegisterComponentFromNewPrefab(prefab, Lifetime.Scoped);
builder.RegisterComponentOnNewGameObject<YourBehaviour>(Lifetime.Scoped, "name");
```

You can create a group with a specified parent.

```csharp
builder.UseComponents(parentTransform, components =>
{
// GetComponentInChildren under `parentTransform`
components.AddInHierarchy<YourBehaviour>();

// Instantiate under `parentTransform`
components.AddFromNewPrefab(prefab, Lifetime.Scoped);
components.AddOnNewGameObject<YourBehaviour>(Lifetime.Scoped, "name");
})
```

This is the same as:

```csharp
builder.RegisterComponentInHierarchy<YourBehaviour>()
.UnderTransform(parentTransform);

builder.RegisterComponentFromNewPrefab(prefab, Lifetime.Scoped)
.UnderTransform(parentTransform);
builder.RegisterComponentOnNewGameObject<YourBehaviour>(Lifetime.Scoped, "name");
.UnderTransform(parentTransform);
```


## Execute only Inject for MonoBehaviour on the scene

In VContainer, objects that are not explicitly registered will not be injected. Therefore, execute Register for the object you want to inject.
Expand Down

0 comments on commit 25c2ff9

Please sign in to comment.