如何从 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。