MiniContainer is fast and lightweight DI Container designed to simplify dependency injection in your codebase. With a small code base and easy-to-learn API, it's a great choice for developers who want a fast and reliable solution without the complexity of larger frameworks.
- Constructor injection: Ensures reliable dependency management.
- Scoping: Allows defining the lifetime of dependencies.
- Factories: Uses
Func
as factories for dynamic dependency creation. - Open generics: Supports registering and resolving of generic types.
- Source Generators: Uses Source Generators to improve Resolve performance up to 5-10 times.
- Loosely coupled: Promotes loosely-coupled architecture, so your code can remain decoupled from the framework.
- Platform Agnostic: Can be used outside of the Unity platform.
To begin using MiniContainer, you first need to build your container by registering all the dependencies you will need.
Once your container is built, you can run your entry point and use your registered dependencies.
public class Program
{
[RuntimeInitializeOnLoadMethod]
private static void Main()
{
var container = Build();
Start(container);
}
private static Container Build()
{
var container = new Container();
container.Register<Service>();
container.Register<AnotherService, IAnotherService>();
return container;
}
private static void Start(Container container)
{
container.Resolve<Service>();
}
}
public class Service
{
public Service(IAnotherService anotherService)
{
Debug.Log($"constructor call, got {anotherService}");
}
}
In the following example, Service is registered as self and AnotherService is registered as IAnotherService.
MiniContainer supports registering dependencies in scoped containers, which can be useful for organizing dependencies in different scopes, such as game or menu scopes.
Here's an example of registering and resolving a dependency in a scoped container:
using (var scopeContainer = new Container(container))
{
scopeContainer.Register<ScopedService>();
scopeContainer.Resolve<ScopedService>();
}
Scoped containers can also have a parent container, which allows them to access dependencies registered in the parent container.
When a scoped container is disposed, MiniContainer will automatically dispose all registered IDisposable
dependencies within that scope.
MiniContainer allows you to use Func as a factory to create dependencies. You can register the factory as an instance and use it as a dependency.
Here's an example of registering a Func factory that can create a FactoryProduction instance:
var container = new Container();
container.RegisterInstance<Func<int, FactoryProduction>>(
_ => new FactoryProduction(container.Resolve<AnotherService>(), _));
public Service(Func<int, FactoryProduction> productionFactory)
{
var production = productionFactory(1);
}
MiniContainer allows registration of open generic types, which can be useful for situations where you want to define a dependency based on a generic type, but without specifying the type argument.
Here's an example of registering and resolving a generic type with a type parameter that's not specified:
container.Register(typeof(Logger<>), typeof(ILogger<>));
public Service(ILogger<Service> logger)
{
logger.Log("constructor call");
}
MiniContainer leverages Source Generators to eliminate reflection and create dependencies directly using constructor, with a fallback to reflection when necessary.
To use source-generated code you need to import "Code generation" sample in Package Manager.
Then you'll need to register your instance constructors, these constructors are named as "AssemblyName"_GeneratedInstanceConstructor
.
Here's an example of setting the instance constructors:
Container.SetInstanceConstructors(
new AssemblyCSharp_GeneratedInstanceConstructor(),
new ReflectionInstanceConstructor());
Requires Unity 2021.3+
You can select "Add package from git URL" in Package Manager and paste https://github.com/Voresh/MiniContainer.git?path=Unity/Assets/MiniContainer
there.
Or you can add "com.voresh.minicontainer": "https://github.com/Voresh/MiniContainer.git?path=Unity/Assets/MiniContainer",
to Packages/manifest.json
MIT License
Copyright (c) 2023 Vladimir Oreshkov aka Voresh
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.