简体   繁体   中英

ASP.NET Core. Configure DI to get the same object for different interfaces

I have middleware, that do some job and create object. I need to inject this object into controller. So far I see solution with extra layer by adding to DI some factory that create such objects by extracting already created one from context.Items['myobject_created_and_placed_here_in_middleware'] .

Also I'm considering another way:

public interface IReader
{
    string Get();
}

public interface IWriter
{
    string Set(string value);
}

public class Object1 : IReader, IWriter
{
    public string s1 { get; set; }
    public string Get()
    {
        return this.s1;
    }

    public string Set(string value)
    {
        this.s1 = value;
        return s1;
    }
}

public class Middleware1
{
    RequestDelegate next;
    private readonly IReader _reader;


    public Middleware1(RequestDelegate next, IReader reader)
    {
        this.next = next;
        _reader = reader;
    }

    public async Task Invoke(HttpContext context)
    {
        var test1 = _reader.Get();
        await next.Invoke(context);
    }
}

public class Middleware2
{
    RequestDelegate next;
    private readonly IWriter _writer;


    public Middleware2(RequestDelegate next, IWriter writer)
    {
        this.next = next;
        _writer = writer;
    }

    public async Task Invoke(HttpContext context)
    {
        _writer.Set("13168AAE-C886-453E-B655-ECE5D14645D9");
        await next.Invoke(context);
    }
}

Startup.cs:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole();

        app.UseMiddleware<Middleware2>();
        app.UseMiddleware<Middleware1>();

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    }

So far it doesn't work.
This returns different objects:

services.AddScoped<IReader,Object1>();
services.AddScoped<IWriter, Object1>();

This can't resolve interface:

services.AddScoped<Object1>();

The question is: how to register it in DI and get the same object for different interfaces per request.

FYI: it is possible to share a single object between DI registrations, even between Scoped and Transient registrations. Try to avoid it if possible.

public interface IGodObject { } //empty marker interface
public interface IWriter { }
public interface IReader { }
public class GodObject : IGodObject, IReader, IWriter { }

services.AddScoped<IGodObject>(p =>
{
    return new GodObject();
});

services.AddScoped<IReader>(p =>
{
    return p.GetService<IGodObject>() as IReader;
});

services.AddScoped<IWriter>(p =>
{
    return p.GetService<IGodObject>() as IWriter;
});

Personally I would stick with the Items property in the HttpContext , as its sole purpose is storing items for the scope of a request.

If, however, you would like to use an object instance in DI I suggest you merge the IReader and IWriter into a single interface and add that to the DI container.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM