如何从 View ASP.NET MVC 6 切换存储库
How to switch repositories from View ASP.NET MVC 6
我有数据库和 xml 存储库。我如何才能从应用程序的视图切换存储库?例如,视图有一个 select:
<select>
<option value="xml">XML Storage</option>
<option value="sqldb">SQL Database</option>
</select>
Program.cs
// builder.Services.AddSingleton<ITaskRepository, TaskRepositoryXML>();
// builder.Services.AddSingleton<ICategoryRepository, CategoryRepositoryXML>();
builder.Services.AddSingleton<ITaskRepository, TaskRepositoryDB>();
builder.Services.AddSingleton<ICategoryRepository, CategoryRepositoryDB>();
您可能有一些想法?谢谢!
首先,您应该注册您的服务以便在运行时使用它们,即使您希望稍后可以选择 select。
一种简单而可爱的方法是使用简单的 Factory
模式。我为您的 TaskRepository
添加了实现,但您应该为 CategoryRepository
:
执行准确的实现
public interface ITaskRepository
{
IEnumerable<string> GetTasks();
}
public class XmlTaskRepository : ITaskRepository
{
public IEnumerable<string> GetTasks() =>
new[] { "Task1 from xml", "Task2 from xml" };
}
public class SqlTaskRepository : ITaskRepository
{
public IEnumerable<string> GetTasks() =>
new[] { "Task1 from sql", "Task2 from sql" };
}
现在你需要一个工厂,为了方便起见,我实现了一个简单的版本:
public class TaskRepositoryFactory
{
public ITaskRepository GetTaskRepository(string userSelection) =>
userSelection.ToLowerInvariant() switch
{
"xml" => new XmlTaskRepository(),
"sql" => new SqlTaskRepository(),
_ => throw new ArgumentException(nameof(userSelection))
};
}
最后,你必须注册你的Factory
,我建议使用Scope
而不是Singletone
(假设你的持久层是基于EF Core)
builder.Services.AddScoped<TaskRepositoryFactory>();
这就是您需要为 DI 做的所有事情。但是,为了说明,我添加了一个简单的页面并注入了工厂的具体class,并根据QueryString
切换到首选服务(这很荒谬,但我认为足以展示用法)
public class IndexModel : PageModel
{
private readonly TaskRepositoryFactory _factory;
public IndexModel(TaskRepositoryFactory factory)
{
_factory = factory;
}
public List<string> TasksData { get; set; } = new();
public void OnGet([FromQuery] string selection = "")
{
if (!string.IsNullOrEmpty(selection))
{
var repo = _factory.GetTaskRepository(selection);
TasksData = repo.GetTasks().ToList();
}
}
}
razor 页面有一个简单的迭代如下:
@page
@model IndexModel
@foreach (var dt in Model.TasksData)
{
<span>@dt</span><br />
}
我们可以解决所有的依赖关系,但我们可以决定在工厂模式的帮助下实例化哪个 TaskRepository。
我有数据库和 xml 存储库。我如何才能从应用程序的视图切换存储库?例如,视图有一个 select:
<select>
<option value="xml">XML Storage</option>
<option value="sqldb">SQL Database</option>
</select>
Program.cs
// builder.Services.AddSingleton<ITaskRepository, TaskRepositoryXML>();
// builder.Services.AddSingleton<ICategoryRepository, CategoryRepositoryXML>();
builder.Services.AddSingleton<ITaskRepository, TaskRepositoryDB>();
builder.Services.AddSingleton<ICategoryRepository, CategoryRepositoryDB>();
您可能有一些想法?谢谢!
首先,您应该注册您的服务以便在运行时使用它们,即使您希望稍后可以选择 select。
一种简单而可爱的方法是使用简单的 Factory
模式。我为您的 TaskRepository
添加了实现,但您应该为 CategoryRepository
:
public interface ITaskRepository
{
IEnumerable<string> GetTasks();
}
public class XmlTaskRepository : ITaskRepository
{
public IEnumerable<string> GetTasks() =>
new[] { "Task1 from xml", "Task2 from xml" };
}
public class SqlTaskRepository : ITaskRepository
{
public IEnumerable<string> GetTasks() =>
new[] { "Task1 from sql", "Task2 from sql" };
}
现在你需要一个工厂,为了方便起见,我实现了一个简单的版本:
public class TaskRepositoryFactory
{
public ITaskRepository GetTaskRepository(string userSelection) =>
userSelection.ToLowerInvariant() switch
{
"xml" => new XmlTaskRepository(),
"sql" => new SqlTaskRepository(),
_ => throw new ArgumentException(nameof(userSelection))
};
}
最后,你必须注册你的Factory
,我建议使用Scope
而不是Singletone
(假设你的持久层是基于EF Core)
builder.Services.AddScoped<TaskRepositoryFactory>();
这就是您需要为 DI 做的所有事情。但是,为了说明,我添加了一个简单的页面并注入了工厂的具体class,并根据QueryString
切换到首选服务(这很荒谬,但我认为足以展示用法)
public class IndexModel : PageModel
{
private readonly TaskRepositoryFactory _factory;
public IndexModel(TaskRepositoryFactory factory)
{
_factory = factory;
}
public List<string> TasksData { get; set; } = new();
public void OnGet([FromQuery] string selection = "")
{
if (!string.IsNullOrEmpty(selection))
{
var repo = _factory.GetTaskRepository(selection);
TasksData = repo.GetTasks().ToList();
}
}
}
razor 页面有一个简单的迭代如下:
@page
@model IndexModel
@foreach (var dt in Model.TasksData)
{
<span>@dt</span><br />
}
我们可以解决所有的依赖关系,但我们可以决定在工厂模式的帮助下实例化哪个 TaskRepository。