Register Plain C# Type
There are various ways to use Register. Let's take the following complex type as an example.
class ServiceA : IServiceA, IInputPort, IDisposable { /* ... */ }
Register Concrete Type
builder.Register<ServiceA>(Lifetime.Singleton);
It can resolve like this:
class ClassA
{
public ClassA(ServiceA serviceA) { /* ... */ }
}
Register as Interface
builder.Register<IServiceA, ServiceA>();
It can resolve like this:
class ClassA
{
public ClassA(IServiceA serviceA) { /* ... */ }
}
Register as multiple Interface
builder.Register<ServiceA>(Lifetime.Singleton)
.As<IServiceA, IInputPort>();
It can resolve like this:
class ClassA
{
public ClassA(IServiceA serviceA) { /* ... */ }
}
class ClassB
{
public ClassB(IInputPort inputPort) { /* ... */ }
}
Register all implemented interfaces automatically
builder.Register<ServiceA>(Lifetime.Singleton)
.AsImplementedInterfaces();
It can resolve like this:
class ClassA
{
public ClassA(IServiceA serviceA) { /* ... */ }
}
class ClassB
{
public ClassB(IInputPort inputPort) { /* ... */ }
}
Register all implemented interfaces and concrete type
builder.Register<ServiceA>(Lifetime.Singleton)
.AsImplementedInterfaces()
.AsSelf();
It can resolve like this:
class ClassA
{
public ClassA(IServiceA serviceA) { /* ... */ }
}
class ClassB
{
public ClassB(IInputPort inputPort) { /* ... */ }
}
class ClassC
{
public ClassC(ServiceA serviceA) { /* ... */ }
}
Register lifecycle marker interfaces
class GameController : IStartable, ITickable, IDisposable { /* ... */ }
builder.RegisterEntryPoint<GameController>();
This is similar to Register<GameController>(Lifetime.Singleton).AsImplementedInterfaces()
.
The key difference is whether it runs in PlayerLoopSystem or not.
If you want to customize the exception handling for entry points, you can register a callback with the following.
builder.RegisterEntryPointExceptionHandler(ex =>
{
UnityEngine.Debug.LogException(ex);
// Additional process ...
});
If you have multiple EntryPoints, you have the option to use the following declaration as grouping.
builder.UseEntryPoints(entryPoints =>
{
entryPoints.Add<ScopedEntryPointA>();
entryPoints.Add<ScopedEntryPointB>();
entryPoints.Add<ScopedEntryPointC>().AsSelf();
entryPoints.OnException(ex => ...)
});
This is the same as:
builder.RegisterEntryPoint<ScopedEntryPointA>();
builder.RegisterEntryPoint<ScopedEntryPointB>();
builder.RegisterEntryPoint<ScopedEntryPointC>().AsSelf();
builder.RegisterEntryPointExceptionHandler(ex => ...);
See the Plain C# Entry point section for more information.
Register instance
// ...
var obj = new ServiceA();
// ...
builder.RegisterInstance(obj);
RegisterIntance
always has a Singleton
lifetime, so it has no arguments.
It can resolve like this:
class ClassA
{
public ClassA(ServiceA serviceA) { /* ... */ }
}
Instances registered with RegisterInstance are not managed by the container.
- Dispose will not be executed automatically.
- Method Injection will not be executed automatically
If you want the container to manage the created instances, consider using the following instead
Register instance as interface
Use As*
declarations.
builder.RegisterInstance<IInputPort>(serviceA);
builder.RegisterInstance(serviceA)
.As<IServiceA, IInputPort>();
builder.RegisterInstance(serviceA)
.AsImplementedInterfaces();
Register type-specific parameters
If the types are not unique, but you have a dependency you want to inject at startup, you can use the following:
builder.Register<SomeService>(Lifetime.Singleton)
.WithParameter<string>("http://example.com");
Or, you can name a paramter with a key.
builder.Register<SomeService>(Lifetime.Singleton)
.WithParameter("url", "http://example.com");
It can resolve like this:
class SomeService
{
public SomeService(string url) { /* ... */ }
}
This Register only works when being injected into SomeService
.
class OtherClass
{
// ! Error
public OtherClass(string hogehoge) { /* ... */ }
}
Register Open Generics
class GenericType<T>
{
// ...
}
builder.Register(typeof(GenericType<>), Lifetime.Singleton);
It can resolve like this:
class SomeService
{
public SomeService(GenericType<int> closedGenericType) { /* ... */ }
}
In this case, the concrete type is constructed at runtime. We have confirmed that this works with IL2CPP from Unity 2022.1 onwards, but older versions may not support dynamic typedefs.