Dependency injection

Cloud Code has support for dependency injection (DI), which allows you to decouple hard-coded dependencies in your code and make it easier for unit testing. The DI here is based on the similar system created by .Net.

Cloud Code offers support for the following dependency types:

  • Singleton: Singleton dependencies are created once and then injected where needed.
  • Scoped: Scoped dependencies are created once per request. Whether you use it in the constructor or the method itself doesn't matter since they both link to the same object.
  • Transient: Transient dependencies are created every time one is requested. If you request a transient dependency in the constructor and again in a method, those two requests are two separate instances.

Dependency injection setup

In order to set up your dependencies, you must create a class that implements the ICloudCodeSetup interface.

The following example defines a singleton interface and its implementation, but you can also use a scoped or transient dependency by using either AddScoped or AddTransient.

C#

using Unity.Services.CloudCode.Core;

namespace ExampleModule;

public interface IRandomNumber
{
    public int GetRandomNumber();
}

public class LockedRandomNumber : IRandomNumber
{
    private int randomNumber;

    public LockedRandomNumber()
    {
        randomNumber = Random.Shared.Next();
    }

    public int GetRandomNumber()
    {
        return randomNumber;
    }
}

public class ModuleConfig : ICloudCodeSetup
{
    public void Setup(ICloudCodeConfig config)
    {
        config.Dependencies.AddSingleton<IRandomNumber, LockedRandomNumber>();
    }
}

Note that:

  • The singleton generates a random number once, and then keeps it as long as the service is live.
  • The scoped creates a new instance per request but the number stays the same for that request regardless of where you request it.
  • The transient creates a new instance every single time it's requested, and thus returns a random number each time.

Dependency injection usage

To support dependency injection, attribute CloudCodeFunction to your methods along with their class constructors, as the following example demonstrates.

C#

using Unity.Services.CloudCode.Core;

namespace ExampleModule;

public struct DependencyInjectionResult
{
    public int ConstructorNumber;
    public int MethodNumber;
}

public class TestDependencyInjection
{
    private int number;

    public TestDependencyInjection(IRandomNumber randomNumber)
    {
        number = randomNumber.GetRandomNumber();
    }

    [CloudCodeFunction("TestInjection")]
    public DependencyInjectionResult TestInjection(IRandomNumber randomNumber)
    {
        return new DependencyInjectionResult
        {
            // Will always return the same number during the session
            ConstructorNumber = number,
            MethodNumber = randomNumber.GetRandomNumber(),
        };
    }
}

Warning: While the singleton is retained between multiple requests, it is still possible that it's different between requests because Cloud Code scales to multiple pods when needed in order to meet demand.

Refer to Microsoft's documentation on dependency injection usage.