无法解析 Blazor Server 中的数据依赖项

Can't Resolve Data Dependencies in Blazor Server

提问人:SETH BARRERE 提问时间:11/14/2023 更新时间:11/14/2023 访问量:20

问:

我正在尝试在我的 blazor 服务器项目中实现干净的体系结构。在我的应用层中,我有这项服务。

public class GetOrganizationDetailQuery : IGetOrganizationDetailQuery
{
    private readonly IDatabaseService _database;

    public GetOrganizationDetailQuery(IDatabaseService database) 
    {
        _database = database;
    }

    public OrganizationDetailModel Execute(Guid id)
    {
        var organization = _database.Organizations
                        .Where(x => x.Id == id)
                        .Select(x => new OrganizationDetailModel()
                        {
                            Id = x.Id,
                            Name = x.Name
                        })
                        .Single();
        return organization;
    }
}

该接口也在应用程序项目中定义。

public interface IDatabaseService
{
    DbSet<Domain.Organization> Organizations { get; }

    void Save();
}

我的数据层依赖于应用层,它定义了上述接口的实现。

public class DatabaseService : DbContext, IDatabaseService
{
    ...

    public DbSet<Organization> Organizations { get; set; }

    public void Save()
    {
        this.SaveChanges();
    }
}

最后,在我的 UI 层中,我尝试注入查询,以便我可以在页面上使用它。

程序.cs

builder.Services.AddScoped<IGetOrganizationDetailQuery, GetOrganizationDetailQuery>();

这会引发异常;无法构造服务。

有没有办法在不从我的UI层添加对数据层的引用的情况下解决此问题?

asp.net-core blazor clean-architecture

评论

0赞 MrC aka Shaun Curtis 11/14/2023
GetOrganizationDetailQuery是应用层中定义的合约的基础架构层实现。WASM 版本可以调用 API 服务来获取数据。你的接口应该只定义 .请参阅本文,其中可能会提供一些指导,包括使用 request 和 result 对象。IGetOrganizationDetailQueryIGetOrganizationDetailQueryExecute

答:

1赞 Kurt Hamilton 11/14/2023 #1

最终,您需要引用定义接口和实现的所有项目,以便能够使用依赖项注入。

我的偏好是将所有依赖项注册移动到一个专用项目中。这(在我看来)使应用程序更干净,并意味着我可以避免引用实现项目(例如实体框架实现)。

这种方法的缺点是你需要能够抽象依赖容器本身,但这(同样,我的观点)是一个值得权衡的。

Dependency Registrar 项目

// The dependency container abstraction, 
// implemented in the app project. 
// You can add any additional registration functionality 
// that you require.
public interface IDependencyContainer
{
  IDependencyContainer AddScoped<TInterface, TImplementation>()
    where TInterface : class
    where TImplementation : class, TInterface;
}

// The dependency registration itself, 
// called by the app project
public static class DependencyConfig
{
  public static void RegisterDependencies(
    IDependencyContainer container, 
    IConfiguration config)
  {
    container.AddScoped<
      IGetOrganizationDetailQuery, 
      GetOrganizationDetailQuery>();
  }
}

应用项目

// The implementation of the 
// dependency container abstraction.
// Really just a wrapper for the methods
// available on IServiceCollection.
// Requires that you add a reference to the 
// Microsoft.Extensions.Configuration.Abstractions NuGet package
public class DependencyContainer : IDependencyContainer
{
  private readonly IServiceCollection _services;

  public DependencyContainer(IServiceCollection services)
  {
    _services = services;
  }

  public IDependencyContainer AddScoped<TInterface, 
    TImplementation>()
    where TInterface : class
    where TImplementation : class, TInterface
  {
    _services.AddScoped<TInterface, TImplementation>();
    return this;
  }
}

程序.cs

// Invoke dependency registration in the Program.cs file
IDependencyContainer container = 
  new DependencyContainer(builder.Services);
DependencyConfig.RegisterDependencies(container, 
  builder.Configuration);