Show / Hide Table of Contents
    Important

    You are looking at the 1.5 documentation

    Orleans 2.0 is a significant overhaul from the 1.x versions. You can find 2.0 documentation here.

    What is Dependency Injection

    Dependency injection (DI) is a software design pattern that implements inversion of control for resolving dependencies.

    Orleans is using the abstraction written by the developers of ASP.NET Core. For a detailed explanation about how it works, check out the official documentation.

    DI in Orleans

    Dependency Injection is currently supported only on the server side within Orleans.

    Orleans makes it possible to inject dependencies into application Grains.

    However Orleans supports every container dependent injection mechanisms, one of the most commonly used method is constructor injection.

    Theoretically any type can be injected which was previously registered in a IServiceCollection during Silo startup. Note*: As Orleans is evolving, as of the current plans it will be possible to leverage dependency injection in other application classes as well, like StreamProviders.

    Configuring DI

    The DI configuration is a global configuration value and must be configured there.

    Orleans is using a similar approach as ASP.NET Core to configure DI. You must have a Startup class within your application which must contain a ConfigureServices method. It must return an object instance of type: IServiceProvider.

    Configuration is done by specifying the type of your Startup class via one of the methods described below.

    Note: Previously DI configuration was specified at the cluster node level, this was changed in the recent release.

    Configuring from Code

    It is possible to tell Orleans what Startup type you like to use with code based configuration. There is an extension method named UseStartup on the ClusterConfiguration class which you can use to do that.

    var configuration = new ClusterConfiguration();
    
    configuration.UseStartupType<MyApplication.Configuration.MyStartup>();
    

    Configuring via XML

    To register your Startup class with Orleans you add a Startup element to the Defaults section and in the Type attribute you specify the assembly-qualified name for the type.

    <?xml version="1.0" encoding="utf-8" ?>
    <tns:OrleansConfiguration xmlns:tns="urn:orleans">
      <tns:Defaults>
        <tns:Startup Type="MyApplication.Configuration.Startup,MyApplication" />
      </tns:Defaults>
    </tns:OrleansConfiguration>
    

    Example

    Here is a complete Startup class example:

    namespace MyApplication.Configuration
    {
        public class MyStartup
        {
            public IServiceProvider ConfigureServices(IServiceCollection services)
            {
                services.AddSingleton<IInjectedService, InjectedService>();
    
                return services.BuildServiceProvider();
            }
        }
    }
    

    This example shows how a Grain can utilize IInjectedService via constructor injection and also the complete declaration and implementation of the injected service:

    public interface ISimpleDIGrain : IGrainWithIntegerKey
    {
        Task<long> GetTicksFromService();
    }
    
    public class SimpleDIGrain : Grain, ISimpleDIGrain
    {
        private readonly IInjectedService injectedService;
    
        public SimpleDIGrain(IInjectedService injectedService)
        {
            this.injectedService = injectedService;
        }
    
        public Task<long> GetTicksFromService()
        {
            return injectedService.GetTicks();
        }
    }
    
    public interface IInjectedService
    {
        Task<long> GetTicks();
    }
    
    public class InjectedService : IInjectedService
    {
        public Task<long> GetTicks()
        {
            return Task.FromResult(DateTime.UtcNow.Ticks);
        }
    }
    

    Test Framework Integration

    DI truly shines when coupled with a testing framework to verify the correctness of the code that build. You can read about the components for testing in Orleans by following our tutorials.

    You will need to do two things to set up DI with tests. First you will need to implement mocks of your services. This is done in our example using Moq, a popular mocking framework for .NET. Here is an example of mocking a service.

    public class MockServices
    {
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            var mockInjectedService = new Mock<IInjectedService>();
    
            mockInjectedService.Setup(t => t.GetTicks()).Returns(knownDateTime);
            services.AddSingleton<IInjectedService>(mockInjectedService.Object);
            return services.BuildServiceProvider();
        }
    }
    

    To include these services in your test silo, you will need to specify MockServices as the silo startup class. Here is an example of doing this.

    [TestClass]
    public class IInjectedServiceTests: TestingSiloHost
    {
        private static TestingSiloHost host;
    
        [TestInitialize]
        public void Setup()
        {
            if (host == null)
            {
                host = new TestingSiloHost(
                    new TestingSiloOptions
                    {
                        StartSecondary = false,
                        AdjustConfig = clusterConfig =>
                        {
                            clusterConfig.UseStartupType<MockServices>();
                        }
                    });
            }
        }
    }
    
    • Improve this Doc
    Back to top Generated by DocFX