aspnet / DependencyInjection

[Archived] Contains common DI abstractions that ASP.NET Core and Entity Framework Core use. Project moved to https://github.com/aspnet/Extensions

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to add service initializers?

VanKrock opened this issue · comments

So, I have some class for example:

public interface IMyService
{
    void Initialize(string value);
}

public class MyService : IMyService
{
    public MyService(IFirstService firstService, ISecondService secondService)
    {
        this.firstService = firstService;
        this.secondService = secondService;
    }

    private readonly IFirstService firstService;
    private readonly ISecondService secondService;
    string value;

    public void Initialize(string value)
    {
        this.value = value;
    }
}

This class contains string parameter "value".
How I can create initialized instance? May be some extension:

public static class ServiceCollectionExtencions
{
    public static IServiceCollection AddInitialization<TService>(this IServiceCollection serviceCollection, Action<TService> initialization)
    {
        //Add initialization to serviceCollection here
        return serviceCollection;
    }
}

But I don't know how I can to add initialize to IServiceCollection

Extension using

var serviceCollection = new ServiceCollection();
serviceCollection
    .AddTransient<IMyService, MyService>()
    .AddInitialization<IMyService>(service => service.Initialize("MyValue"));

You can use a service factory to do manual construction of your service type. Your factory can construct the type and then call .Initialize(...) on it.

You could also leverage decoration with Scrutor 😉

In this case, you don't actually want to return a separate decorator instance, but utilize the decorator factory to call the Initialize function, then return the same instance:

var serviceCollection = new ServiceCollection();
serviceCollection
    .AddTransient<IMyService, MyService>()
    .Decorate<IMyService>((service, provider) =>
    {
        service.Initialize("MyValue");
        return service;
    });

You could, of course, hide the Decorate call in a separate extension method, like the one above:

using Scrutor;

public static class ServiceCollectionExtencions
{
    public static IServiceCollection AddInitialization<TService>(this IServiceCollection serviceCollection, Action<TService> initialization)
    {
        if (initialization == null)
        {
            throw new ArgumentNullException(nameof(initialization));
        }

        return serviceCollection.Decorate<TService>((service, provider) =>
        {
            initialization(service);
            return service;
        });;
    }
}

@khellang Cool! Exactly what is needed.