【问题标题】:How to Inject Generic Repository(Or Business Logic Layer) Into ViewModel如何将通用存储库(或业务逻辑层)注入 ViewModel
【发布时间】:2021-01-17 19:37:09
【问题描述】:

为简单起见,我想将通用存储库注入到视图模型中。我将 ViewModel 和 Repository 添加到服务集合中,ViewModel 依赖于 Repository。根据我的阅读,应该自动解析 ViewModel 的构造函数参数,因为它使用的是 IConfiguration。我已经尝试在 Services 中显式实例化 ViewModel,但仍然出现相同的运行时错误,并且在创建存储库的另一个实例时似乎无法达到目的。

Repository/IRepository 看起来像这样

    public class Repository<TPoco, TDatabaseConnection> : IRepository<TPoco, TDatabaseConnection>
            where TPoco : class
            where TDatabaseConnection : IDbConnection, new()
    {

        public Repository(IConfiguration configuration, string connectionName = "DefaultConnection" )//SqlConnectionConfiguration configuration) //(string connectionString)
        {
            _connectionString = configuration.GetConnectionString(connectionName);
            _configuration = configuration;
        }


...

查看模型

    public class PersonViewModel
    {
        private IRepository<Person, IDbConnection> _PersonRepository;

        public List<Person> Persons { get; set; }

        public PersonViewModel(IRepository<Person, IDbConnection> personRepository)
        {
            _PersonRepository=personRepository;
        }
...

在 Startup.cs 文件中,我添加如下服务:

    services.AddScoped<IRepository<Person, SQLiteConnection>, Repository<Person, SQLiteConnection>>();
    services.AddScoped<PersonViewModel>();  //runtime errors here

我收到两个运行时错误 (System.AggregateException)


Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: BlazorInjection.ViewModels.PersonViewModel Lifetime: Scoped ImplementationType: BlazorInjection.ViewModels.PersonViewModel': Unable to resolve service for type 'DapperRepository.IRepository`2[BlazorInjection.Models.Person,System.Data.IDbConnection]' while attempting to activate 'BlazorInjection.ViewModels.PersonViewModel'.

Inner Exception 2:
InvalidOperationException: Unable to resolve service for type 'DapperRepository.IRepository`2[BlazorInjection.Models.Person,System.Data.IDbConnection]' while attempting to activate 'BlazorInjection.ViewModels.PersonViewModel'.

我错过了一个概念吗?我该如何纠正这个问题?

【问题讨论】:

标签: c# asp.net-core .net-core dependency-injection blazor


【解决方案1】:

将类结构更改为:

public class PersonViewModel
{
    private IRepository<Person> _PersonRepository;

    public List<Person> Persons { get; set; }

    public PersonViewModel(IRepository<Person> personRepository)
    {
        _PersonRepository = personRepository;
    }
}

public interface IDbConnection
{

}

public class Person { }


public interface IRepository<TPoco> { }

public class SQLiteConnection : IDbConnection 
{
    private string _connectionString;
    private IConfiguration _configuration;

    public SQLiteConnection(IConfiguration configuration, string connectionStringName)
    {
        _connectionString = configuration.GetConnectionString(connectionStringName);
        _configuration = configuration;
    }
}

public class Repository<TPoco> : IRepository<TPoco>
    where TPoco : class
{
    public IDbConnection Connection { get; }

    public Repository(IDbConnection connection)
    {
        Connection = connection;
    }
}

Startup.cs相比,只需更改为

services.AddScoped<IDbConnection>(sp => ActivatorUtilities.CreateInstance<SQLiteConnection>(sp, "defaultConnectionStringName"));
        services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
        services.AddScoped<PersonViewModel>();

注意通用存储库注册,它可以轻松扩展您的数据层。 ActivatorUtilities 允许您将当前范围 container 服务与自定义参数结合起来。从设计的角度来看,我认为这种方式(一个通用的注入连接)也更好,因为您的存储库客户端不需要知道底层数据库实现。

【讨论】:

  • 我试过了。我收到关于隐式转换的错误:There is no implicit reference conversion from 'DapperRepository.Repository&lt;BlazorInjection.Models.Person, System.Data.SQLite.SQLiteConnection&gt;' to 'DapperRepository.IRepository&lt;BlazorInjection.Models.Person, System.Data.IDbConnection&gt;'.Does System.Data.SQLiteConnection not implement IDbConnection?
  • 也试过了。类似的错误。它要求参数,所以我这样做了。 services.AddScoped&lt;IRepository&lt;Person, IDbConnection&gt;&gt;(sp =&gt; new Repository&lt;Person, SQLiteConnection&gt;(Configuration)); 我收到两个错误:CS1662 Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type 和第二个要求明确 cast.hmm ?
  • 有什么理由需要存储库是双重通用的吗?如果没有,您可以将 IDbConnection 作为构造函数参数
  • 我让我的存储库实例化 dbconnection。我想没有必要。我可以尝试将其作为参数传入
  • 请查看修改后的答案
猜你喜欢
  • 2011-03-29
  • 1970-01-01
  • 1970-01-01
  • 2013-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
  • 2010-12-18
相关资源
最近更新 更多