[英]Injecting Dependency programmatically asp.net core
我只是從Asp.net core
依賴注入開始 ,而我的概念可能不准確。 這篇docs.asp.net帖子介紹了如何將上下文注入控制器。 從測試角度看,我對注入幾乎沒有困惑。 假設我們有以下情形:
public interface ITasksRepository
{
public void Create();
}
//This is fake implementation, using fake DbContext for testing purpose
public class TasksRepositoryFake : ITasksRepository
{
public void Create()
{
FakeDbContext.Add(sometask);
//logic;
}
}
//This is actual implementation, using actual DbContext
public class TasksRepository : ITasksRepository
{
public void Create()
{
DbContext.Add(someTask);
//logic;
}
}
現在,為了在控制器中注入上下文,我們將其設計為:
public class TasksController : Controller
{
public ITasksRepository TaskItems { get; set; }
public TodoController(ITaskRepository taskItems)
{
TaskItems = taskItems;
}
//other logic
}
asp.net core
提供的內置功能是,我們可以在啟動類中注冊依賴項注入,如下所示:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
services.AddSingleton<ITasksRepository, TasksRepositoryFake>();
}
根據此邏輯,我的TaskRepositoryFake
將被注入到控制器中。 到目前為止,一切都很清楚。 我對此的疑問/困惑如下:
問題:
首先回答您的問題:是的,您可以通過編程方式注入依賴項。 通過使用工廠,通常會基於運行時值注入依賴項。 AddSingleton有一個實現工廠的重載,因此您的用例的基本示例如下:
public class Startup
{
public bool IsTesting { get; }
public Startup(IHostingEnvironment env)
{
IsTesting = env.EnvironmentName == "Testing";
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ISomeRepository>(sp => IsTesting ? (ISomeRepository)new SomeRepository() : (ISomeRepository) new FakesomeRepository());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, ISomeRepository someRepository)
{
app.UseIISPlatformHandler();
app.Run(async (context) =>
{
await context.Response.WriteAsync($"Hello World from {nameof(someRepository)}!");
});
}
// Entry point for the application.
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}
您的TasksRepository的代碼行如下所示:
services.AddSingleton<ITaskRepository>(sp => isTesting?(ITasksRepository)new TasksRepositoryFake(): (ITasksRespository)new TasksRepository() );
更好的方法是將其放入工廠(同樣以我的示例為例):
services.AddSingleton<ISomeRepository>(sp => SomeRepositoryFactory.CreatSomeRepository(IsTesting));
我希望您能看到它如何幫助您將其設置為基於配置,基於環境或您想要的設置。 如果您有興趣,我在這里通過抽象工廠撰寫了更多有關基於運行時值的DI的文章。
話雖如此,通過單元測試,我只是將偽造品注入正在測試的類中。 在那里進行單元測試仍然可以向您自己和您的同事證明代碼仍然按預期運行。 並通過集成測試,我將使用所有假貨創建一個特殊的StartUp類,並將其提供給測試主機,因為ASP.NET Core允許您這樣做。 您可以在此處了解有關測試主機的更多信息: https : //docs.asp.net/en/latest/testing/integration-testing.html
希望這可以幫助。
更新將強制類型轉換添加到接口,因為三元條件無法分辨。 加上添加了一些基本示例。
您可以注入基於配置的依賴關系或基於環境的依賴關系,或同時注入兩者。
選項1:基於環境
public IHostingEnvironment env{ get; set; }
public Startup(IHostingEnvironment env)
{
this.env = env;
}
public void ConfigureServices(IServiceCollection services)
{
if (env.IsDevelopment())
{
// register other fake dependencies
services.AddSingleton<ITasksRepository, TasksRepositoryFake>();
}
else
{
// register other real dependencies
services.AddSingleton<ITasksRepository, TasksRepository>();
}
}
選項2:基於配置
public IConfigurationRoot Configuration { get; set; }
public Startup()
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
var isFakeMode= Configuration["ServiceRegistrationMode"] == "Fake";
if (isFakeMode)
{
// register other fake dependencies
services.AddSingleton<ITasksRepository, TasksRepositoryFake>();
}
else
{
// register other real dependencies
services.AddSingleton<ITasksRepository, TasksRepository>();
}
}
選項3:基於環境+基於配置
public IConfigurationRoot Configuration { get; set; }
public IHostingEnvironment env{ get; set; }
public Startup(IHostingEnvironment env)
{
this.env = env;
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
var isFakeMode = Configuration["ServiceRegistrationMode"] == "Fake";
if (env.IsDevelopment() && isFakeMode)
{
// register other fake dependencies
services.AddSingleton<ITasksRepository, TasksRepositoryFake>();
}
else
{
// register other real dependencies
services.AddSingleton<ITasksRepository, TasksRepository>();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.