C# NET内核。配置DI以获得不同接口的相同对象
我有中间件,它做一些工作并创建对象。我需要将这个对象注入控制器。 到目前为止,我看到的解决方案是通过在DI中添加一些工厂,这些工厂通过从C# NET内核。配置DI以获得不同接口的相同对象,c#,asp.net-core,asp.net-core-mvc,asp.net-core-webapi,C#,Asp.net Core,Asp.net Core Mvc,Asp.net Core Webapi,我有中间件,它做一些工作并创建对象。我需要将这个对象注入控制器。 到目前为止,我看到的解决方案是通过在DI中添加一些工厂,这些工厂通过从上下文中提取已经创建的对象来创建这样的对象 我也在考虑另一种方式: public interface IReader { string Get(); } public interface IWriter { string Set(string value); } public class Object1 : IReader, IWriter
上下文中提取已经创建的对象来创建这样的对象
我也在考虑另一种方式:
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!");
});
}
public void配置(IApplicationBuilder应用程序、IHostingEnvironment环境、iLogger工厂)
{
loggerFactory.AddConsole();
app.UseMiddleware();
app.UseMiddleware();
app.Run(异步(上下文)=>
{
wait context.Response.WriteAsync(“Hello World!”);
});
}
到目前为止,它还不起作用。
这将返回不同的对象:
services.AddScoped<IReader,Object1>();
services.AddScoped<IWriter, Object1>();
services.addScope();
services.addScope();
这无法解析接口:
services.AddScoped<Object1>();
services.addScope();
问题是:如何在DI中注册它,并为每个请求的不同接口获取相同的对象。我个人会坚持使用HttpContext
中的Items
属性,因为它的唯一目的是存储请求范围内的项
但是,如果您想在DI中使用对象实例,我建议您将IReader
和IWriter
合并到一个接口中,并将其添加到DI容器中。FYI:可以在DI注册之间共享一个对象,甚至在范围内的和暂时的注册之间。如果可能的话,尽量避免
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;
});
公共接口IGodObject{}//空标记接口
公共接口IWriter{}
公共接口IReader{}
公共类GodObject:IGodObject、IReader、IWriter{}
services.AddScoped(p=>
{
返回新的GodObject();
});
services.AddScoped(p=>
{
返回p.GetService()作为IReader;
});
services.AddScoped(p=>
{
将p.GetService()作为IWriter返回;
});
工厂实际上是您唯一的选择,因为大多数DI容器都是围绕对象的类型标识设计的。如果给它两种类型,它将创建两个不同的对象。这就是DI容器存在自定义工厂调用的原因,因为有时自动化的简单方法并不适用于所有情况。@juunas我相信不是这样。我正在询问如何将中间件中创建的对象传递给控制器,并提出了一些想法。因为这个对象应该根据请求创建(贯穿整个管道),所以我在这里看不到重复。嗯,没错。我可能有点草率地使用了这个标志。因此,我可以创建接口ICompose:IReader,IWriter
。然而,我应该(??)在我的控制器/中间件中使用这个ICompose
,然后使用casting(但它没有任何意义)。我想避免这样的事情。因为没有人能从口袋里得到答案,我想我的逻辑不是很流行,所以asp.net内核不支持标准的逻辑,所以我不得不使用Items。很好的提示。这应该被标记为答案。您还可以通过删除大括号和“return”关键字使所有这些注册成为一行。而且,第一次注册可以是services.addScope()