Dependency Injection
This example shows how to integrate Lexis with dependency injection containers.
Interface-Based Design
Lexis provides ILocalizationService for DI scenarios:
csharp
public interface ILocalizationService
{
Locale CurrentLocale { get; }
IReadOnlyList<Locale> AvailableLocales { get; }
event Action<Locale> OnLocaleChanged;
void Initialize(LocalizationSettings settings = null);
void SetLocale(string localeCode);
string Get(string key, params object[] args);
bool HasTranslation(string key);
}Basic DI Setup
csharp
using Lexis;
using UnityEngine;
public class DISetup : MonoBehaviour
{
void ConfigureServices(IServiceContainer container)
{
// Create service with custom settings
var settings = Resources.Load<LocalizationSettings>("CustomSettings");
var service = new LocalizationService();
service.Initialize(settings);
// Register with DI container
container.RegisterInstance<ILocalizationService>(service);
// Connect to static facade (optional, for convenience)
Localization.Service = service;
}
}Zenject Integration
Installer
csharp
using Lexis;
using UnityEngine;
using Zenject;
public class LocalizationInstaller : MonoInstaller
{
[SerializeField] private LocalizationSettings settings;
public override void InstallBindings()
{
// Create and initialize service
var service = new LocalizationService();
service.Initialize(settings);
// Bind as singleton
Container.Bind<ILocalizationService>()
.FromInstance(service)
.AsSingle();
// Optional: connect to static facade
Container.Bind<IInitializable>()
.To<LocalizationFacadeConnector>()
.AsSingle();
}
}
public class LocalizationFacadeConnector : IInitializable
{
private readonly ILocalizationService _service;
public LocalizationFacadeConnector(ILocalizationService service)
{
_service = service;
}
public void Initialize()
{
Localization.Service = _service;
}
}Consumer
csharp
using Lexis;
using UnityEngine;
using Zenject;
public class LocalizedUI : MonoBehaviour
{
private ILocalizationService _localization;
[Inject]
public void Construct(ILocalizationService localization)
{
_localization = localization;
}
void Start()
{
UpdateUI();
_localization.OnLocaleChanged += _ => UpdateUI();
}
void UpdateUI()
{
titleText.text = _localization.Get("ui.title");
}
}VContainer Integration
Registration
csharp
using Lexis;
using VContainer;
using VContainer.Unity;
public class GameLifetimeScope : LifetimeScope
{
[SerializeField] private LocalizationSettings settings;
protected override void Configure(IContainerBuilder builder)
{
// Create service
var service = new LocalizationService();
service.Initialize(settings);
// Register
builder.RegisterInstance<ILocalizationService>(service);
// Entry point for facade connection
builder.RegisterEntryPoint<LocalizationEntryPoint>();
}
}
public class LocalizationEntryPoint : IStartable
{
private readonly ILocalizationService _service;
public LocalizationEntryPoint(ILocalizationService service)
{
_service = service;
}
public void Start()
{
Localization.Service = _service;
}
}Consumer
csharp
using Lexis;
using VContainer;
public class LocalizedPresenter
{
private readonly ILocalizationService _localization;
private readonly IView _view;
[Inject]
public LocalizedPresenter(ILocalizationService localization, IView view)
{
_localization = localization;
_view = view;
}
public void Initialize()
{
_view.SetTitle(_localization.Get("ui.title"));
}
}Testing with Mock
csharp
using Lexis;
using NUnit.Framework;
using NSubstitute;
public class LocalizedUITests
{
[Test]
public void UpdateUI_SetsCorrectTitle()
{
// Arrange
var mockService = Substitute.For<ILocalizationService>();
mockService.Get("ui.title").Returns("Test Title");
var ui = new LocalizedUI(mockService);
// Act
ui.UpdateUI();
// Assert
Assert.AreEqual("Test Title", ui.TitleText);
}
}Non-MonoBehaviour Classes
csharp
using Lexis;
public class GameUI
{
private readonly ILocalizationService _localization;
public GameUI(ILocalizationService localization)
{
_localization = localization;
}
public string GetTitle() => _localization.Get("game.title");
public string GetFormattedScore(int score)
{
return _localization.Get("score.format", score);
}
}Best Practices
- Use interfaces - Depend on
ILocalizationService, not concrete types - Initialize once - Create and configure the service at startup
- Connect facade optionally - Useful for components that can't use DI
- Dispose properly - Call
Dispose()on the service when done - Mock for tests - Use the interface to create test doubles
